Spero che questo sia un post valido qui, è una combinazione di problemi C# e hardware.C# prestazioni che variano a causa della memoria
Sto analizzando il nostro server perché abbiamo riscontrato problemi con le prestazioni della nostra libreria quant (scritta in C#). Ho simulato gli stessi problemi di prestazioni con un semplice codice C#, che comporta un utilizzo molto intenso della memoria.
Il codice di seguito è in una funzione generata da un threadpool, fino a un massimo di 32 thread (poiché il nostro server ha 4x CPU x 8 core ciascuno).
Questo è tutto su Net 3.5
Il problema è che stiamo ottenendo selvaggiamente differenti prestazioni. Eseguo la funzione qui sotto 1000 volte. Il tempo medio impiegato per il codice da eseguire potrebbe essere, ad esempio, 3.5s, ma il più veloce sarà solo 1.2s e il più lento sarà 7s- per la stessa identica funzione!
ho graficamente l'utilizzo della memoria contro i tempi e ci doesnt sembrano essere alcuna correlazione con il GC calci in.
Una cosa che ho notato è che durante l'esecuzione in un singolo thread i tempi sono identici e non vi non è una deviazione selvaggia. Ho anche testato algoritmi legati alla CPU e anche i tempi sono identici. Questo ci ha portato a chiederci se il bus di memoria non può farcela.
Mi chiedevo potrebbe essere un altro problema .net o C#, o è qualcosa correlato al nostro hardware? Questa sarebbe la stessa esperienza se avessi usato C++ o Java ?? Stiamo usando 4x Intel x7550 con 32 GB di RAM. C'è un modo per aggirare questo problema in generale?
Stopwatch watch = new Stopwatch();
watch.Start();
List<byte> list1 = new List<byte>();
List<byte> list2 = new List<byte>();
List<byte> list3 = new List<byte>();
int Size1 = 10000000;
int Size2 = 2 * Size1;
int Size3 = Size1;
for (int i = 0; i < Size1; i++)
{
list1.Add(57);
}
for (int i = 0; i < Size2; i = i + 2)
{
list2.Add(56);
}
for (int i = 0; i < Size3; i++)
{
byte temp = list1.ElementAt(i);
byte temp2 = list2.ElementAt(i);
list3.Add(temp);
list2[i] = temp;
list1[i] = temp2;
}
watch.Stop();
(il codice è solo pensata per sottolineare la memoria)
vorrei includere il codice di thread, ma abbiamo usato una libreria di thread non standard.
EDIT: Ho ridotto "size1" a 100000, che in pratica non utilizza molta memoria e ho ancora un sacco di jitter. Questo suggerisce che non è la quantità di memoria che viene trasferita, ma la frequenza delle acquisizioni di memoria?
Sono in corso altri processi durante il benchmark? Anche il sistema operativo ha bisogno del tempo della CPU. Se stai utilizzando tutti i core virtuali durante il tuo benchmark, sei virtualmente (perdonatemi il gioco di parole) garantito che i processi non correlati richiederanno del tempo di CPU durante il test. –
Non abbiamo abbastanza informazioni per fare altro che speculare. Detto questo, i miei soldi sono sulla tua "libreria threadpool non standard" che non assegna abbastanza thread per eseguirlo in parallelo. Se si eseguono 50 copie e si assegnano solo 20 thread (ad esempio), 10 iterazioni dovranno attendere (in media) altre 2 iterazioni da completare affinché un thread si liberi. Questo potrebbe spiegare le deviazioni che stai vedendo. –
Solo un'idea: dal momento che sembra conoscere la dimensione della lista, dovresti passarla al costruttore (o usare semplicemente gli array). Quindi si evitano le ridistribuzioni se gli array sottostanti. –