Вот это простая программа, которая только потребляет 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
Это примитивный итератор и должно быть заменено чем-то более сложным - например, если вам нужно 37 МБ для вызова RamInit с элементами Collection a и 1M, вы должны начать с 2M элементов с более чем.
И вы должны выбрать шаги в двоичном поиске, например, если 20M слишком мало, отметьте 128, затем (20 + 128)/2, а затем avg этого, в зависимости от успеха или неудачи с нижним пределом или верхний предел.
Поскольку HashMap хранит 2 входа на элемент, он может начинаться с примерно двойного размера 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.
Я знаю, что уже несколько раз отвечал на этот материал, но я даже не могу найти свои собственные сообщения для него. Вот очень короткая, неполная версия для горячей точки: каждый объект имеет 2 слова накладных расходов и выровнен по 8 байт. массивы имеют дополнительный 4 байта для размера. Размер ссылки зависит от JVM-битности, но сжатые oops существуют для куч <32gb на 64-битных системах. – Voo
Интересно, может ли visualvm сделать это для вас ... theres профилировщик памяти, но я никогда не использовал его. –
Мне не удалось найти ответы на него: = D Если вы можете найти один из своих старых ответов, который охватывает это, это было бы потрясающе. –