Skip to content

Instantly share code, notes, and snippets.

@nnabeyang
Last active December 12, 2015 07:28
Show Gist options
  • Save nnabeyang/4736847 to your computer and use it in GitHub Desktop.
Save nnabeyang/4736847 to your computer and use it in GitHub Desktop.
Javaのメモリ使用量(64bitマシン)の計算するプログラムを書きました。プリミティブなフィールドのみに対応します。"gen_nomethod_class.py"はテスト用のクラスの生成のために使っています。
#!/usr/bin/env python2.7
#encoding:utf-8
import random
def gen():
fmt = """public class %(CLASS)s {
public boolean %(BOOLEAN)s;
public int %(INT)s;
public char %(CHAR)s;
public long %(LONG)s;
public double %(DOUBLE)s;
public boolean[] %(BI)s;
public char[] %(AC)s;
public int[] %(AI)s;
public long[] %(LI)s;
public double[] %(DI)s;
}"""
for i in range(4):
class_name = "NoMethodClass%d" % i
b = ["b%d" % d for d in range(random.randint(1, 4))]
c = ["c%d" % d for d in range(random.randint(1, 4))]
i = ["i%d" % d for d in range(random.randint(1, 4))]
do = ["d%d" % d for d in range(random.randint(1, 4))]
l = ["l%d" % d for d in range(random.randint(1, 4))]
bi = "bi = new boolean[%d]" % pow(2, random.randint(3, 10))
ac = "ci = new char[%d]" % pow(2, random.randint(3, 10))
ai = "ai = new int[%d]" % pow(2, random.randint(3, 10))
li = "li = new long[%d]" % pow(2, random.randint(3, 10))
di = "di = new double[%d]" % pow(2, random.randint(3, 10))
with open("%s.java" % class_name,"w") as f:
f.write(fmt % {
"CLASS":class_name,
"BOOLEAN": ",".join(b),
"CHAR": ",".join(c),
"INT": ",".join(i),
"LONG": ",".join(l),
"DOUBLE": ",".join(do),
"BI": bi,
"AC": ac,
"AI": ai,
"LI": li,
"DI": di
})
gen()
import java.lang.reflect.Field;
public class MemoryCheck {
private static int OVERHEAD = 16;
public static int calcUsage(Class testClass) throws Exception {
int usage = OVERHEAD;
Object obj = testClass.newInstance();
for (Field field : testClass.getDeclaredFields()) {
String fieldName = field.getName();
String fieldType = field.getType().getSimpleName();
if (fieldType.equals("boolean"))
usage += 1;
else if (fieldType.equals("char"))
usage += 2;
else if (fieldType.equals("int"))
usage += 4;
else if (fieldType.equals("long"))
usage += 8;
else if (fieldType.equals("double"))
usage += 8;
else if (fieldType.equals("boolean[]")) {
usage += 8; // ref
int n = ((boolean[]) field.get(obj)).length;
usage += 1 * n + 24;
}
else if (fieldType.equals("char[]")) {
usage += 8; // ref
int n = ((char[]) field.get(obj)).length;
usage += 2 * n + 24;
}
else if (fieldType.equals("int[]")) {
usage += 8; // ref
int n = ((int[]) field.get(obj)).length;
usage += 4 * n + 24;
}
else if (fieldType.equals("long[]")) {
usage += 8; // ref
int n = ((long[]) field.get(obj)).length;
usage += 8 * n + 24;
}
else if (fieldType.equals("double[]")) {
usage += 8; // ref
int n = ((double[]) field.get(obj)).length;
usage += 8 * n + 24;
}
else {
throw new Exception(fieldType);
}
}
while (usage % 8 != 0) usage++; // padding
return usage;
}
public static void main(String[] args) throws Exception {
if (args.length != 1) throw new IllegalArgumentException();
int usage = calcUsage(Class.forName(args[0]));
System.out.println("usage = " + usage + " bytes");
}
}
import junit.framework.TestCase;
public class Test_MemoryCheck extends TestCase {
public void testTestClass0() {
try {
assertEquals(1992, MemoryCheck.calcUsage(Class.forName("NoMethodClass0")));
} catch(Exception e) {
fail(e.getMessage());
}
}
public void testTestClass1() {
try {
assertEquals(8912, MemoryCheck.calcUsage(NoMethodClass1.class));
} catch(Exception e) {
fail(e.getMessage());
}
}
public void testTestClass2() {
try {
assertEquals(6720, MemoryCheck.calcUsage(NoMethodClass2.class));
} catch(Exception e) {
fail(e.getMessage());
}
}
public void testTestClass3() {
try {
assertEquals(10056, MemoryCheck.calcUsage(NoMethodClass3.class));
} catch(Exception e) {
fail(e.getMessage());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment