2015-06-10 1 views
-1

Я пишу небольшое приложение, которое позволяет пользователям тестировать программы. В настоящее время я анализирую результаты некоторых тестовых программ, и я очень удивлен тем, что вижу. ПК, который я использую для измерений, имеет ОЗУ 16 ГБ. Ниже приведены исходный код и результаты для алгоритма интеграции Монте-Карло.Как объяснить высокую загрузку памяти Java в эталонном

Это источник 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; 
} 

Когда взглянуть на монитор ресурсов во время выполнения, я могу видеть, что в то время как «Private» значение ресурса монитор всегда остается довольно маленьким (около 10 МБ), значение «Commit» огромно (~ 400 МБ) для Java-программ. Это не относится к версии C#. Я полагаю, что это имеет какое-то отношение к проблеме, однако в моем измерительном коде я использую свойство PrivateMemorySize64.

Мой вопрос: насколько возможно, что версия Java потребляет гораздо больше памяти, чем версия C#, и если это связано с ошибкой с моей стороны, как я могу получить более точные измерения?

+0

Я мало что знаю об этом, но не потому, что Java задерживает управление памятью (сборку мусора), чтобы ускорить процесс. –

+1

Если вы не даете Java никаких параметров '-Xms/-Xmx', они с радостью выделяют 1/4 вашей общей памяти в JVM и используют ее с безрассудным отказом. – Kayaman

ответ

0

Память для небольшой программы всегда является проблемой для приложений Java. Если вы пробовали некоторые услуги OJ как leetcode, вы увидите, что реализация Java всегда имеет больший объем памяти и более длительное время загрузки по сравнению с C/C++/Python/JS/C#:

enter image description here

Различные JVM имеет различные аргументы запуска (например, JRockit: Tuning For a Small Memory Footprint), и, возможно, вы могли бы попробовать.

Также я думаю, что этот ответ might explain something.