folgenden Code Angenommen:Atomic AddOrUpdate für eine C# Wörterbuch
if (myDictionary.ContainsKey(aKey))
myDictionary[aKey] = aValue;
else
myDictionary.Add(aKey, aValue);
Dieser Code das Wörterbuch zweimal zugreift, einmal zu bestimmen, ob aKey
vorhanden sind, ein anderes Mal für die Aktualisierung (falls vorhanden) oder das Hinzufügen (falls nicht vorhanden). Ich denke, die Leistung dieser Methode ist "akzeptabel", wenn dieser Code nur wenige Male ausgeführt wird. In meiner Anwendung wird jedoch ein ähnlicher Code ungefähr 500K mal ausgeführt. Ich habe meinen Code profiliert und er zeigt 80% der CPU-Zeit, die für diesen Abschnitt aufgewendet wurde (siehe folgende Abbildung). Dies motiviert zu einer Verbesserung.
Beachten Sie, dass das Wörterbuch lambdas
ist.
Erste Abhilfe ist einfach:
myDictionary[aKey] = aValue;
Wenn aKey
existieren es Wert ist mit aValue
ersetzt wird; Wenn nicht vorhanden, wird KeyValuePair
mit aKey
als Schlüssel und aValue
als Wert zu myDictionary
hinzugefügt. Diese Methode hat jedoch zwei Nachteile:
Zuerst, Sie wissen nicht, ob aKey
existiert oder nicht, die Sie von zusätzlichen Logiken verhindert. Zum Beispiel können Sie nicht folgenden Code neu schreiben, basierend auf dieser Problemumgehung:
int addCounter = 0, updateCounter = 0;
if (myDictionary.ContainsKey(aKey))
{
myDictionary[aKey] = aValue;
addCounter++;
}
else
{
myDictionary.Add(aKey, aValue);
updateCounter++;
}
Zweiter, kann das Update nicht eine Funktion des alten Wertes sein. Zum Beispiel können Sie eine Logik ähnlich wie nicht tun:
if (myDictionary.ContainsKey(aKey))
myDictionary[aKey] = (myDictionary[aKey] * 2) + aValue;
else
myDictionary.Add(aKey, aValue);
Zweite Abhilfe ist ConcurrentDictionary
zu verwenden. Es ist klar, dass delegates
wir das zweite genannte Problem lösen können; aber mir ist immer noch nicht klar, wie wir das erste Problem behandeln können.
Nur zur Erinnerung, mein Anliegen ist es, zu beschleunigen. Da es nur einen Thread gibt, der diese Prozedur verwendet, glaube ich nicht, dass die Penetration der Parallelität (mit Sperren) für nur einen Thread die Verwendung von ConcurrentDictionary
wert ist.
Fehle ich einen Punkt? Hat jemand einen besseren Vorschlag?
Nur um zu bestätigen einmal mehr: Das ist single-threaded, gibt es keinen Grund für hier Zugang zu synchronisieren?Sie brauchen also eigentlich keine * atomare * Operation, sondern nur eine schnelle Möglichkeit, einen Wert festzulegen und herauszufinden, ob Sie einen Wert hinzugefügt oder aktualisiert haben. – poke
Sie können überprüfen, ob 'Count' von Elementen im Wörterbuch nach' myDictionary [aKey] = aValue' geändert wurde, um den ersten Nachteil zu umgehen. – ghord
Als Erstes cache designedRegions [_i] in einer Loop-Scoped-Variablen und cache designedRegions [_i] .lambdas in einer anderen Loop-Scope-Variablen. Siehst du die 4,5% CPU-Zeit in designedRegions [_i] μ-? Wenn Sie das alleine machen, wird Sie das wahrscheinlich erheblich beschleunigen. –