我正在对HashMap,LinkedHashMap插件进行一些性能测试。我正在测试的操作是在插入后在内存中插入和大小。
我能够做到,插入测试并且还能够使用以下逻辑提取size in memory after insertion
-
long myTotalMemoryBefore = Runtime.getRuntime().totalMemory();
/* Fill the hashmap or linkedhashmap */
long myTotalMemoryAfter = Runtime.getRuntime().totalMemory();
long myHashMapMemory = myTotalMemoryAfter - myTotalMemoryBefore;
我有一个文本文件,其中包含200万个英文单词,其频率为此格式 -
hello 100
world 5000
good 2000
bad 9000
...
现在我逐行读取此文件并将其存储在HashMap
和LinkeddHashMap
中,以便我可以在插入后测量内存中的插入性能和大小以及下面的代码。< / p>
我有一个单独的类文件,其中我有两个方法,一个用于HashMap
,另一个用于LinkedHashMap
性能测试,它们都按顺序运行,首先运行HashMap测试,然后是linkedHashMap测试将运行 -
public void hashMapTest() {
Map<String, String> wordTest = new HashMap<String, String>();
long myTotalMemoryBefore = Runtime.getRuntime().totalMemory();
String line = reader.readLine();
while (line != null && !line.isEmpty()) {
// split the string on whitespace
String[] splittedString = line.split("\\s+");
String split1 = splittedString[0].toLowerCase().trim();
Integer split2 = Integer.parseInt(splittedString[1].trim());
// now put it in HashMap as key value pair
wordTest.put(split1, split2);
line = reader.readLine();
}
long myTotalMemoryAfter = Runtime.getRuntime().totalMemory();
long myHashMapMemory = (myTotalMemoryAfter - myTotalMemoryBefore) / 1024;
System.out.println(myHashMapMemory);
}
public void linkedHashMapTest() {
Map<String, String> wordTest = new LinkedHashMap<String, String>();
long myTotalMemoryBefore = Runtime.getRuntime().totalMemory();
String line = reader.readLine();
while (line != null && !line.isEmpty()) {
// split the string on whitespace
String[] splittedString = line.split("\\s+");
String split1 = splittedString[0].toLowerCase().trim();
Integer split2 = Integer.parseInt(splittedString[1].trim());
// now put it in LinkedHashMap as key value pair
wordTest.put(split1, split2);
line = reader.readLine();
}
long myTotalMemoryAfter = Runtime.getRuntime().totalMemory();
long myLinkedHashMapMemory = (myTotalMemoryAfter - myTotalMemoryBefore) / 1024;
System.out.println(myLinkedHashMapMemory); // this is coming as zero always or negative value
}
我看到一个非常奇怪的问题 - 对于HashMap性能测试,我可以看到myHashMapMemory
中有一些值,但在myLinkedHashMapMemory
变量中,它总是具有零值或负值。
有没有想过为什么会这样,以及如何避免这个问题?一般来说,为什么我看到零值或负值?
答案 0 :(得分:1)
要测量已用内存,我们需要关闭线程分配缓冲区-XX:-UseTLAB
,然后关闭这个
Runtime rt = Runtime.getRuntime();
long m0 = rt.totalMemory() - rt.freeMemory(); //used memory
Object obj = new Object();
long m1 = rt.totalMemory() - rt.freeMemory();
System.out.println(m1 - m0);
将在内存中显示正确的java.lang.Object大小 - 在我的情况下为16个字节
答案 1 :(得分:0)
快速提问:为什么有两种相同的方法......?只需将地图作为参数传递?
但是除此之外:如果你按顺序运行它们,那么当你进入第二种方法时,gc可能已经从第一个哈希映射中踢出并删除了东西。任何基于这种原始方法的内存扫描都可能无法给出正确的估计值。
换句话说:如果第二张地图已被gc-ed,则第二张地图可能占据与第一张地图相同的存储空间。此外,根据jvm和设置,如果未使用(例如,在其中的所有内容都已被gc-ed之后),jvm实际上可以将操作系统的内存返回给操作系统。
答案 2 :(得分:0)
这可能是因为其他人提到的gc的行为。 我想说的是,对于如此大量的数据,地图实现都很糟糕。我已经测试过,每当数据大于几百万字节时,你必须自己为这种工作实现Map接口。
答案 3 :(得分:0)
我认为Evgeniy是对的。在jdk1.7中,TLAB设置为true default。当新线程启动时,即使没有创建对象也将分配TLAB。因此,您可以关闭TLAB并再次尝试。 由于gc因素,你应该尝试更多次,并且你最好提高伊甸园区域以避免年轻的gc。