代码设计:性能与可维护性
语境化
我正在测试上下文中使用soot框架实现字节码指示器,我想知道哪个设计更好。
我正在为我正在检测的类中的每个方法构建TraceMethod对象,并且我想在多个类上运行此指令器。
哪个选项提供更高的性能(时空)?
选项1 :(地图)
public class TraceMethod { boolean[] decisionNodeList; boolean[] targetList; Map<Integer,List> dependenciesMap; Map<Integer,List> decisionNodeBranchDistance; }
选项2 :(对象)
public class TraceMethod { ArrayList targets = new ArrayList(); ArrayList decisionNodes = new ArrayList(); } public class DecisionNode { int id; Double branchDistance; boolean reached; } public class Target { int id; boolean reached; List dependencies; }
我自己实施了选项2 ,但我的老板建议我选择1 ,他认为这是“更轻”。 我在本文“ Class Object vs Hashmap ”中看到,HashMaps使用的内存多于Objects,但我仍然不相信我的解决方案( 选项2 )更好。
它是一个简单的细节,但我想确定我使用的是最佳解决方案,我关心的是性能(时空)。 我知道第二种选择在可维护性方面更好,但如果它不是最优的,我可以牺牲它。
方法1具有更快速且使用更少空间的有效性。
特别是对于字节码指示器,我首先实现方法1。
然后当它工作时,将两个列表替换为使用原始类型而不是Integer和Double对象的非generics列表。
注意,int需要4个字节,而Integer(Object)需要16到20个字节,具体取决于机器(PC上16个,android下20个)。
可以用GrowingIntArray
替换GrowingIntArray
(我已经在Apache的统计包中找到了,如果我记得正确的话),它使用了原始的int。 (或者,一旦你知道内容不能再改变,可能只需用int []替换)然后你只需编写自己的GrowingDoubleArray(或使用double [])
记住collections很方便但速度较慢。
对象使用的空间比基元多4倍。
字节码指示器需要性能,它不是每周运行一次的软件。
最后,我不会用非通用的地图替换那个地图,这对我来说似乎有很多工作要做。 但你可以尝试它作为最后一步。
作为最后的优化步骤:查看列表或地图中有多少元素。 如果它通常小于16(您必须尝试它),您可以切换到线性搜索,这是最快的,对于非常少的元素。 一旦元素数量超过特定数量,您甚至可以使代码智能化以切换搜索算法。 (Sun / Oracle java会这样做,而Apple / ios会这样做)在他们的一些集合中。 但是,最后一步将使您的代码更加复杂。
空间作为例外:
DecisionNode:16为类+ 4(id)+ 20(Double)+4(布尔)= 44 + 4填充,然后是8 = 48字节的下一个倍数。
一般来说,你应该总是去维护,而不是假设的性能。 这有几个很好的理由:
- 我们倾向于对数组与HashMap之间的速度差异着迷,但在实际的企业应用程序中,这些差异并不足以说明应用程序速度的明显差异。
- 应用程序中最常见的瓶颈是数据库或网络。
- JVM在某种程度上优化了代码
由于代码可维护,您的应用程序不太可能出现性能问题。 更有可能的情况是,当你有数百万行无法维护的代码时,你的老板会用光钱。
- 用于HTTP错误的Javaexception类是什么?
- Maven Resources插件:如何将资源复制到目标文件夹并保留时间戳?
- 使用CQL jdbc驱动程序时应该是什么连接字符串
- 可以精确表示为浮点数/双精度的整数范围
- FTPSClient返回MalformedServerReplyException:无法解析响应代码
- 用于删除Java项目中不必要的依赖项的工具
- Java SSL / TLS忽略过期的证书? (java.security.cert.CertPathValidatorException:时间戳检查失败)
- 在数据库模式中hibernate二级缓存和ON DELETE CASCADE
- hibernate是否保留LinkedHashSet的顺序,如果是,如何?