Ho scritto un programma di test di dimensioni ridotte e sono rimasto sorpreso del motivo per cui la soluzione lock {}
è più veloce di lock-free ma con attributo [ThreadStatic]
su variabile statica..NET: ThreadStatic vs lock {}. Perché ThreadStaticAttribute riduce le prestazioni?
[ThreadStatic] frammento:
[ThreadStatic]
private static long ms_Acc;
public static void RunTest()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int one = 1;
for (int i = 0; i < 100 * 1000 * 1000; ++i) {
ms_Acc += one;
ms_Acc /= one;
}
stopwatch.Stop();
Console.WriteLine("Time taken: {0}", stopwatch.Elapsed.TotalSeconds);
}
blocco {} frammento:
private static long ms_Acc;
private static object ms_Lock = new object();
public static void RunTest()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
int one = 1;
for (int i = 0; i < 100 * 1000 * 1000; ++i) {
lock (ms_Lock) {
ms_Acc += one;
ms_Acc /= one;
}
}
stopwatch.Stop();
Console.WriteLine("Time taken: {0}", stopwatch.Elapsed.TotalSeconds);
}
Sulla mia macchina prima frammento richiede 4,2 secondi; secondo - 3,2 secondi, che è 1 secondo più veloce. Senza ThreadStatic e blocco - 1,2 secondi.
Sono curioso perché l'attributo [ThreadStatic]
in questo semplice esempio ne aggiunge così tanti per programmare il tempo di esecuzione?
UPDATE: Mi dispiace molto, ma questi risultati sono per la build DEBUG
. Per RELEASE
uno ho ottenuto numeri completamente diversi: (1.2; 2.4; 1.2). Per i numeri DEBUG
erano (4,2; 3,2; 1,2).
Quindi, per la build RELEASE
sembra non esserci la penalità di prestazione [ThreadStatic]
.
che non è quello che vedo sul mio QuadCore. Se compilo Release su Any Cpu ottengo 0.81s per il primo snippet e 4.5s per il secondo.Il caso banale senza sicurezza del filo richiede 0,46 secondi. – FuleSnabel
Hai ragione. Sono passato da 'Debug' a' Release' mode e sono diventato simile ai tuoi risultati. – Roman
Può aiutare a leggere il codice smontato per capire perché si ottengono risultati sorprendenti. – FuleSnabel