Last active
December 12, 2015 07:28
-
-
Save nnabeyang/4736847 to your computer and use it in GitHub Desktop.
Javaのメモリ使用量(64bitマシン)の計算するプログラムを書きました。プリミティブなフィールドのみに対応します。"gen_nomethod_class.py"はテスト用のクラスの生成のために使っています。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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