Сравнение производительности многопоточности между Java и C#. Почему Java становится медленнее? (графики и полный код включены)

Недавно я провел тесты на Java и C# для 1000 задач, которые должны быть запланированы в пуле потоков. Сервер имеет 4 физических процессора, каждый из которых имеет 8 ядер. ОС — Server 2008, имеет 32 ГБ памяти и каждый процессор — Xeon x7550 Westmere/Nehalem-C.

Короче говоря, реализация Java намного быстрее, чем C# при 4 потоках, но намного медленнее по мере увеличения числа потоков. Также кажется, что C# стал быстрее на итерацию, когда количество потоков увеличилось. Графики включены в этот пост:

Java vs C# with a threadpool size of 4 threadsJava vs C# with a threadpool size of 32 threadsPeter's Java answer (see below) vs C#, for 32 threads

Реализация Java была написана на 64-битной JVM Hotspot, с Java 7 и с использованием пула потоков Executor Service, который я нашел в Интернете (см. ниже). Я также установил JVM на параллельный сборщик мусора.

C# был написан на .net 3.5, а пул потоков взят из codeproject: http://www.codeproject.com/Articles/7933/Smart-Thread-Pool

(я включил код ниже).

Мои вопросы:

1) Почему Java становится медленнее, а C# — быстрее?

2) Почему время выполнения C# сильно колеблется? (Это наш главный вопрос)

Мы задавались вопросом, были ли колебания C# вызваны перегрузкой шины памяти....

Код (Пожалуйста, не выделяйте ошибки с блокировкой, это не имеет отношения к моим целям) :

Java

import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class PoolDemo {

    static long FastestMemory = 2000000000;
    static long SlowestMemory = 0;
    static long TotalTime;
    static long[] FileArray;
    static DataOutputStream outs;
    static FileOutputStream fout;

  public static void main(String[] args) throws InterruptedException, FileNotFoundException {

        int Iterations = Integer.parseInt(args[0]);
        int ThreadSize = Integer.parseInt(args[1]);

        FileArray = new long[Iterations];
        fout = new FileOutputStream("server_testing.csv");

        // fixed pool, unlimited queue
        ExecutorService service = Executors.newFixedThreadPool(ThreadSize);
        //ThreadPoolExecutor executor = (ThreadPoolExecutor) service;

        for(int i = 0; i SlowestMemory)
            {
                SlowestMemory = Duration;
            }
        }
      }
}

С#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Amib.Threading;
using System.Diagnostics;
using System.IO;
using System.Runtime;


namespace ServerTesting
{
    class Program
    {
        static long FastestMemory = 2000000000;
        static long SlowestMemory = 0;
        static long TotalTime = 0;
        static int[] FileOutput;
        static byte myByte = 56;

        static System.IO.StreamWriter timeFile;
        static System.IO.StreamWriter memoryFile;

        static void Main(string[] args)
        {
            Console.WriteLine("Concurrent GC enabled: " + GCSettings.IsServerGC);
            int Threads =   Int32.Parse(args[1]);
            int Iterations = Int32.Parse(args[0]);

            timeFile = new System.IO.StreamWriter(Threads + "_" + Iterations + "_" + "time.csv");

            FileOutput = new int[Iterations];
            TestMemory(Threads, Iterations);

            for (int j = 0; j < Iterations; j++)
            {
                timeFile.WriteLine(FileOutput[j] + ",");
            }

            timeFile.Close();
            Console.ReadLine();
        }

        private static void TestMemory(int threads, int iterations)
        {
            SmartThreadPool pool = new SmartThreadPool();
            pool.MaxThreads = threads;
            Console.WriteLine("Launching " + iterations + " calculators with " + pool.MaxThreads + " threads");
            for (int i = 0; i < iterations; i++)
            {
                pool.QueueWorkItem(new WorkItemCallback(MemoryIntensiveTask), i);
            }
            pool.WaitForIdle();
            double avg = TotalTime/iterations;
            Console.WriteLine("Avg Memory Time : " + avg);
            Console.WriteLine("Fastest: " + FastestMemory + " ms");
            Console.WriteLine("Slowest: " + SlowestMemory + " ms");
        }



        private static object MemoryIntensiveTask(object args)
        {

            DateTime start = DateTime.Now;
            int Size1 = 10000000;
            int Size2 = 2 * Size1;
            int Size3 = Size1;

            byte[] list1 = new byte[Size1];
            byte[] list2 = new byte[Size2];
            byte[] list3 = new byte[Size3];

            for (int i = 0; i < Size1; i++)
            {
                list1[i] = myByte;
            }

            for (int i = 0; i < Size2; i = i + 2)
            {
                list2[i] = myByte;
            }

            for (int i = 0; i < Size3; i++)
            {
                byte temp = list1[i];
                byte temp2 = list2[i];
                list3[i] = temp;
                list2[i] = temp;
                list1[i] = temp2;
            }

            DateTime finish = DateTime.Now;
            TimeSpan ts = finish - start;
            long duration = ts.Milliseconds;

            Console.WriteLine("Individual Time " + args + " \t: " + duration);

            FileOutput[(int)args] = (int)duration;
            TotalTime += duration;

            if (duration < FastestMemory)
            {
                FastestMemory = duration;
            }
            if (duration > SlowestMemory)
            {
                SlowestMemory = duration;
            }
            return null;
        }
    }
}

10
задан Peter Lawrey 10 April 2016 в 13:53
поделиться