Недавно я провел тесты на Java и C# для 1000 задач, которые должны быть запланированы в пуле потоков. Сервер имеет 4 физических процессора, каждый из которых имеет 8 ядер. ОС — Server 2008, имеет 32 ГБ памяти и каждый процессор — Xeon x7550 Westmere/Nehalem-C.
Короче говоря, реализация Java намного быстрее, чем C# при 4 потоках, но намного медленнее по мере увеличения числа потоков. Также кажется, что C# стал быстрее на итерацию, когда количество потоков увеличилось. Графики включены в этот пост:
Реализация 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;
}
}
}