有没有人有各种数据结构的粗略经验法估算器列表? e.g。
- 阵列
- 解释
- 包含HashMap
- LinkedLists
我记得在不同的地方看到过一些估计值,但我现在似乎无法找到。
我知道它实际上是非常复杂的,特别是像HashMaps这样的东西,但我正在寻找一些非常粗糙的东西,比如:
Memory(HashMap) = fixedOverhead + variableOverhead * tableSize + A*numKeys + B*numValues + Memory(allKeys) + Memory(allValues)
当然它会因此而变化很大,但是,即使是粗略的2因素估计也会非常有用。
答案 0 :(得分:3)
答案 1 :(得分:2)
此表非常详尽,并且精确处理以每个条目/元素的字节数为单位测量的JDK实现选项。如果您想在自己的计算机上执行此操作 - 如果您在另一台计算机上运行,可能 - 此Google代码网站将允许您下载其来源。 http://code.google.com/p/memory-measurer/wiki/ElementCostInDataStructures
答案 2 :(得分:0)
这非常粗糙,但这些估计应该是正确的。这些是针对简单的数据结构,不包括长度变量或任何其他倾向于包含在Java中的附加内容。
其中dataType是存储的数据类型
Array: (length n)
n*sizeOf(dataType)
LinkedList:
n*(sizeOf(dataType)+sizeOf(pointer))+sizeOf(pointer[head pointer])
List:
Array-backed=SpaceEfficiency(Array)
LinkedList-backed=SpaceEfficiency(LinkedList)
HashMap: with v values, k keys
v*sizeOf(valueDataType)
Tree: k-way tree with n nodes
n*(sizeOf(nodeDataType)+(k*sizeOf(pointer)))+sizeOf(pointer[head pointer])
Graph: e edges, v vertices
AdjacencyList:
at most: v*((v*sizeOf(vertexDataType))+(e*sizeOf(pointer))) fully connected graph
at least: v*sizeOf(vertexDataType) disconnected graph
AdjacencyMatrix:
v^2*sizeOf(int)
答案 3 :(得分:0)
这是一个简单的程序,只占用RAM:
import java.util.*;
/**
RamInit (c) GPLv3
@author Stefan Wagner
@date Do 22. Mär 08:40:40 CET 2012
*/
public class RamInit
{
private java.lang.Object consumer;
public RamInit (char type, int size)
{
switch (type)
{
case 'a': Integer [] ai = new Integer [size];
for (int i = 0; i < size; ++i)
ai[i] = i;
consumer = ai;
break;
case 'l': List<Integer> li = new ArrayList<Integer> ();
for (int i = 0; i < size; ++i)
li.add (i);
consumer = li;
break;
case 'h': HashMap <Integer, Integer> hm = new HashMap <Integer, Integer> ();
for (int i = 0; i < size; ++i)
hm.put (i, size - i);
consumer = hm;
break;
case 'L': LinkedList <Integer> ll = new LinkedList <Integer> ();
for (int i = 0; i < size; ++i)
ll.add (i);
consumer = ll;
break;
default: System.err.println ("invalid: " + type);
}
}
public static void main (String args[])
{
char type = 'a';
int size = 1000000; // 1M
if (args.length == 2)
{
type = args[0].charAt (0);
size = Integer.parseInt (args[1]);
}
try {
new RamInit (type, size);
}
catch (OutOfMemoryError oome)
{
System.exit (1);
}
}
}
这是一个非常简单的测试脚本:
#!/bin/bash
iterProg () {
ram=$1
maxram=$2
typ=$3
size=$4
# echo java -Xmx${ram}M RamInit $typ $((size*1000*1000))
echo -n "."
java -Xmx${ram}M RamInit $typ $((size*1000*1000)) && echo -en "\n"$typ $size ${ram}M || {
if (($ram==$maxram))
then
# echo "fail"
return
else
iterProg $((ram+1)) $maxram $typ $size
fi
}
}
# try from 16 MB to 256
for typ in {a,l,h,L}; do
for size in {1,2,4}; do
iterProg $((size*17+1)) 256 $typ $size
done
done
它是一个原始迭代器,应该用更复杂的东西代替 - 例如,如果你需要37MB来调用带有Collection a和1M元素的RamInit,那么你应该从2M元素开始,而不是那个。
你应该选择二元搜索中的步骤,例如,如果20M太少,检查128,然后是(20 + 128)/ 2,然后是平均值,取决于成功或失败的下限或者上限。
由于HashMap每个元素存储2个Int,因此它可以大致以List / Array / Vector的双倍大小开始。然而 - 时间像箭一样飞,在写作时,结果已经结束:
bash iterRamFind.sh
..
a 1 19M.....
a 2 39M...............
a 4 83M..
l 1 19M.......
l 2 41M.......................
l 4 91M..............................................
h 1 63M.............................................................................................
h 2 127M...........................................................................................................................................................................................
h 4 255M......................
L 1 39M.................................................
L 2 83M...............................................................................................
L 4 163
值17从第一次实验中解释了自己。 我们可以看到,尺寸几乎呈线性增长。
修改代码以检查你使用的影响Longs取决于你 - 我想你最终会得到2倍。
答案 4 :(得分:0)
来自twitter工作人员的Infoq, there is a presentation infoq-11-nov-jvmperformance.mp3:Pdf-slides,音频:mp3和视频。
它处理了很多关于JVM中对象大小的集合和其他细节。