[英]Large memory footprint on simple Java code
我正在spoj
解决问题,系统显示我的程序占用了1341M
的内存。 当我查看其他语言的提交内容时,它们需要~3M
,比〜400倍少!
我的代码如下:
class Main {
static List<BigInteger> numbers = new ArrayList<>();
static {
BigInteger max = BigInteger.TEN.pow(100);
numbers.add(BigInteger.ONE);
numbers.add(BigInteger.valueOf(2l));
BigInteger last = numbers.get(1);
while (last.compareTo(max) <= 0) {
numbers.add(numbers.get(numbers.size() - 1).add(numbers.get(numbers.size() - 2)));
last = numbers.get(numbers.size() - 1);
}
}
public static void main(String[] args) throws java.lang.Exception {
BufferedReader bi = new BufferedReader(new InputStreamReader(System.in));
String line;
String delims = " ";
while ((line = bi.readLine()) != null) {
StringTokenizer tokenizer = new StringTokenizer(line, delims);
BigInteger from = new BigInteger(tokenizer.nextToken());
BigInteger to = new BigInteger(tokenizer.nextToken());
if (from.equals(BigInteger.ZERO) && to.equals(BigInteger.ZERO)) {
return;
} else {
System.out.println(countInRange(from, to));
}
}
}
public static int countInRange(BigInteger from, BigInteger to) {
int fromIndex = Collections.binarySearch(numbers, from);
fromIndex = fromIndex < 0 ? Math.abs(fromIndex) - 1 : fromIndex;
int toIndex = Collections.binarySearch(numbers, to);
toIndex = toIndex < 0 ? Math.abs(toIndex) - 1 : toIndex + 1;
return toIndex - fromIndex;
}
}
我认为BufferedReader
是导致高内存消耗的原因。 在这种情况下是否可以显着改善内存占用量? 我并不是说要达到3M
,而是至少要达到100M
左右。
首先 :您如何保留元素的numbers
? 可能会相当多,因为您的最高限额为10 pow 100。
第二 :考虑Java内存模型。 1341M几乎可以容纳32位Java VM。 因此,也许只是在堆上生成对象(所有这些闪亮的new BigInteger
)时,Java产生了很多垃圾内存。 但是,如果您没有正确设置进程的选项,则不会将其返回给操作系统。
您是否实际尝试仅使用100M内存运行程序(通过在Java调用中设置-Xmx100m
选项?
考虑创建一个堆转储并检查(我建议使用Eclipse Memory Profiler来查看正在消耗您的内存。这时我的最佳猜测是:要么是大量的预先计算的数字(它们是什么?对我来说好像是Lucas序列? ),或者只是等待收集垃圾。
快速检查:您确定您的IDE(例如Eclipse或Netbeans)实际上并没有消耗1341MB的内存吗?
我将代码打包到Windows 7,带有64b Oracle JRE 1.8.0.66的x64计算机上的可执行Jar中。 运行代码时,系统仅显示约10MB的内存消耗。 我使用以下方法生成了堆转储:
java -agentlib:hprof=file=snapshot.hprof,format=b -jar number_counter.jar
当使用Eclipse Memory Analyzer进行分析时,所用对象的内存占用量非常低。
一些注意事项:
总结一下,请检查您是否正在监视正确的Java进程,请确保您使用最新的JRE,并确保您没有使用一些不必要的内存管理规则。 您的代码看起来不错,占用空间应小于20 MB。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.