繁体   English   中英

简单的Java代码占用大量内存

[英]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进行分析时,所用对象的内存占用量非常低。

一些注意事项:

  • 数字数组不应太大。 据我了解,它只包含一个斐波那契序列,该序列增长很快,因此我只看到了约500个存储的BigNumbers。
  • 没有真正的理由说明为什么BufferedReader应该具有较大的占用空间。 这是一个经常使用的对象,我确信已经在它上面进行了很好的优化。

总结一下,请检查您是否正在监视正确的Java进程,请确保您使用最新的JRE,并确保您没有使用一些不必要的内存管理规则。 您的代码看起来不错,占用空间应小于20 MB。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM