【问题标题】:How to explain high Java memory consumption in benchmark如何在基准测试中解释高 Java 内存消耗
【发布时间】:2015-08-25 12:00:45
【问题描述】:

我正在编写一个允许用户对程序进行基准测试的小型应用程序。目前我正在分析一些测试程序的结果,我对我所看到的感到非常惊讶。我用于测量的 PC 有 16GB RAM。以下是蒙特卡洛积分算法的源代码和结果。

这是 C# 源代码:

private const long Iterations = 100000000;
static void Main(string[] args)
{
    Random rand = new Random();

    int underCurve = 0;

    for (int i = 0; i < Iterations; i++)
    {
        double x = rand.NextDouble();
        double y = rand.NextDouble();

        if (x * x + y * y <= 1.0)
        {
            underCurve++;
        }
    }
    Console.WriteLine(((double)underCurve / Iterations) * 4.0);
}

以下是 C# 结果:

9785344
9711616
9633792
9691136
9740288
9691136
9768960
9662464
9695232
9662464

Minimum memory consumed = 9633792
Maximum memory consumed = 9785344
Maximum memory consumed = 9704243

这是Java源代码:

private static long Iterations = 100000000;
public static void main(String[] args) {
    Random rand = new Random();

    int underCurve = 0;

    for (int i = 0; i < Iterations; i++){
        double x = rand.nextDouble();
        double y = rand.nextDouble();

        if (x * x + y * y <= 1.0){
            underCurve++;
        }
    }
    System.out.println(((double)underCurve/Iterations)* 4.0);
}

以下是 Java 结果:

454193152
454152192
454201344
454238208
454098944
454258688
454144000
454135808
454189056
454115328

Minimum memory consumed = 454098944
Maximum memory consumed = 454258688
Average memory consumed = 454172672

这是我用来测量进程内存消耗的代码:

private static long MeasureMemoryConsumption(String name, string workingDirectory, String arguments)
{
    Process process = new Process();
    process.StartInfo.WorkingDirectory = workingDirectory;
    process.StartInfo.FileName = name;
    process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.Arguments = arguments;

    long peakMem = 0;
    Thread memMeasuringThread = new Thread(() =>
    {
        while (true)
        {
            try
            {
                process.Refresh();
                peakMem = peakMem < process.PrivateMemorySize64 ? process.PrivateMemorySize64 : peakMem;
            }
            catch (InvalidOperationException)
            {
                //ignore, process didn't start yet
            }
        }
    });

    memMeasuringThread.Start();
    process.Start();
    process.WaitForExit();
    memMeasuringThread.Abort();

    return peakMem;
}

在执行期间查看资源监视器时,我可以看到虽然资源监视器中的“私有”值始终保持很小(大约 10 MB),但“提交”值很大(~400 MB)用于 Java 程序。这不是 C# 版本的情况。我想这与问题有关,但是,在我的测量代码中,我使用的是 PrivateMemorySize64 属性。

我的问题是,Java 版本怎么可能比 C# 版本消耗这么多内存,如果是由于我的错误,我怎样才能获得更准确的测量结果?

【问题讨论】:

  • 我对此了解不多,但不是因为Java会延迟内存管理(垃圾收集)以加快处理速度。
  • 如果你不给Java任何-Xms/-Xmx参数,它会很乐意将你总内存的1/4分配给JVM并肆无忌惮地使用它。

标签: java c# benchmarking


【解决方案1】:

小程序的内存占用一直是 Java 应用程序的一个问题。如果你尝试过一些像 leetcode 这样的 OJ 服务,你会发现与 C/C++/Python/JS/C# 相比,Java 实现总是具有更大的内存占用和更长的启动时间:

不同的 JVM 有不同的启动参数(例如JRockit: Tuning For a Small Memory Footprint),也许你可以试一试。

我也觉得这个答案might explain something

【讨论】:

    猜你喜欢
    • 2011-11-01
    • 1970-01-01
    • 2014-12-30
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 2018-02-15
    • 1970-01-01
    相关资源
    最近更新 更多