问题描述
我正在测试环境中使用soot框架实现字节码指示器,我想知道哪种设计更好。
Im am implementing a bytecode instrumenter using the soot framework in a testing context and I want to know which design is better.
我正在为我正在检测的类中的每个方法构建TraceMethod对象,并且我想在多个类上运行该指导器。
I am building the TraceMethod object for every Method in a Class that I am instrumenting and I want to run this instrumenter on multiple Classes.
哪个选项提供更多性能(时空)?
Which Option offers more performance(Space–time)?
public class TraceMethod {
boolean[] decisionNodeList;
boolean[] targetList;
Map<Integer,List<Integer>> dependenciesMap;
Map<Integer,List<Double>> decisionNodeBranchDistance;
}
选项2 :(对象)
Option 2: (Objects)
public class TraceMethod {
ArrayList<Target> targets = new ArrayList<Target>();
ArrayList<DecisionNode> decisionNodes = new ArrayList<DecisionNode>();
}
public class DecisionNode {
int id;
Double branchDistance;
boolean reached;
}
public class Target {
int id;
boolean reached;
List<DecisionNode> dependencies;
}
我自己实施了选项2 ,但我的老板建议我选项1 ,他认为这是更轻。我在本文中看到,HashMaps使用的内存多于Objects,但我仍然不相信我的解决方案(选项2 )更好。
I have implemented the option 2 by myself, but my boss suggest me the option 1 and he argue that is "lighter". I saw that in this article "Class Object vs Hashmap" that HashMaps use more memory than Objects, but im still not convinced that my solution(option 2) is better.
这是一个简单的细节,但我想确定我是使用最优解决方案,我关心的是性能(时空)。我知道第二种选择在可维护性方面更好,但如果不是最优的话,我可以牺牲它。
Its a simple detail but i want to be sure that I am using the optimal solution, my concern is about performance(Space–time). I know that the second option are way better in term of maintainability but i can sacrifice that if its not optimal.
推荐答案
方法1具有更强的速度和更少的空间。
Approach 1 has the potentical to be much faster and uses less space.
特别是对于字节代码指导者,我首先实现方法1.
然后当它工作时,将两个列表替换为使用基本类型而不是Integer和Double对象的非泛型列表。
Especially for a byte code instrumenter, I would first implement approach 1.
And then when it works, replace both Lists with non generic lists that use primitive types instead of the Integer and Double object.
注意一个int需要4个字节,而一个Integer(Object)需要16到20个字节,具体取决于机器(PC上16个,android上20个)。
Note that an int needs 4 bytes while an Integer (Object) need 16 - 20 bytes, depending on the machine (16 at PC, 20 at android).
列表可以替换为 GrowingIntArray
(我已经在Apache的统计包中找到了,如果我记得正确的话)使用原始的int。 (或者,一旦你知道内容不能再改变,可能只需用int []替换)
然后你只需编写自己的GrowingDoubleArray(或使用double [])
The List can be replaced with GrowingIntArray
(I have found that in an statistic package of Apache if I remeber correctly) which uses primitive ints. (Or maybe just replaced by an int[] once you know that the content cannot change anymore)Then you just write your own GrowingDoubleArray (or use double[])
记住集合很方便但速度较慢。
对象使用的空间比基元多4倍。
Remember Collections are handy but slower.
Objects use 4 times more space than primitives.
字节代码指导员需要性能,它不是一个每周运行一次的软件。
A byte code instrumenter needs performance, it is not a software that is run once a week.
最后我不会用非通用的替换那个地图,这对我来说似乎是
工作。但是你可以尝试最后一步。
Finally I would not replace that Maps with non generic ones, that seems for me to much work. But you may try it as last step.
作为最后的优化步骤:查看列表或地图中有多少元素。如果它通常小于16(你必须试试),你可以切换到线性搜索,
这是最快的,对于非常少的元素。
一旦元素数量超过特定数量,您甚至可以使代码智能化以切换搜索算法。在他们的一些集合中,
(Sun / Oracle java会这样做,以及Apple / ios)。
然而,最后一步将使你的代码更加复杂。
As a final optimization step: look how many elements are in your lists or maps. If that are usually less than 16 (you have to try that out), you may switch to a linear search,which is the fastest, for a very low number of elements.You even can make your code intelligent to switch the search algorithms once the number of elements exceed a specific number.(Sun/Oracle java does this, and Apple/ios, to) in some of their Collections.However this last step will make you code much more complex.
空格作为例子:
DecisionNode:16为类+ 4(id)+ 20(Double)+4(boolean)= 44 + 4填充,然后是8 = 48字节的下一个倍数。
Space as an exmample:
DecisionNode: 16 for the class + 4 (id) + 20 (Double) +4 (boolean) = 44 + 4 padding to then next multiple of 8 = 48 bytes.
这篇关于代码设计:性能与可维护性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!