Ich habe nach dem Prinzip der gemeinsamen Programmierung gearbeitet. Grundsätzlich haben alle Worker-Threads unveränderliche Nur-Lese-Kopien desselben Status, die ( auch nach Verweis ) nie zwischen ihnen geteilt werden . Im Allgemeinen hat dies sehr gut funktioniert.
Jetzt hat jemand einen No-Lock-Singleton-Cache ( z. B. ein statisches Wörterbuch ) eingeführt, auf den alle Threads gleichzeitig zugreifen. Da das Wörterbuch nach dem Start nie geändert wird, gibt es keine Sperren. Es gab keine Thread-Sicherheitsprobleme, aber jetzt ist ein Leistungsabfall zu verzeichnen.
Die Frage ist ... da es keine Sperren gibt, warum sorgt die Einführung dieses Singleton für einen Performance-Hit? Was genau ist unter dem Deckmantel los, das dies erklären könnte?
Zur Bestätigung ist der Zugriff auf diesen neuen Singleton die einzige Änderung, und ich kann dies zuverlässig wiederherstellen, indem ich den Aufruf des Caches auskommentiere.
quelle
Antworten:
Es könnte sein, dass der unveränderliche Zustand eine Cache-Zeile mit etwas Veränderlichem teilt. In diesem Fall kann eine Änderung des nahegelegenen veränderlichen Zustands dazu führen, dass diese Cache-Zeile über Kerne hinweg erneut synchronisiert wird, was die Leistung beeinträchtigen kann.
quelle
false sharing
Szenario, das Sie beschreiben. Um das zu isolieren, muss ich L2 Cache profilieren. Leider handelt es sich hierbei um Referenztypen, sodass das Hinzufügen von Pufferplatz keine Option ist, wenn dies tatsächlich der Fall ist.Ich würde sicherstellen, dass die
Equals()
undGetHashCode()
Methoden der Objekte, die Sie als Schlüssel für das Wörterbuch verwenden, keine unerwarteten nicht-threading-freundlichen Nebenwirkungen haben. Profiling würde hier sehr helfen.Wenn es sich bei Ihren Schlüsseln zufällig um Zeichenfolgen handelt, dann haben Sie es vielleicht schon: Es geht das Gerücht, dass Zeichenfolgen sich wie unveränderliche Objekte verhalten, aber aus Gründen bestimmter Optimierungen intern auf veränderbare Weise implementiert sind, mit allem, was dies in Bezug auf Multithreading mit sich bringt .
Ich würde versuchen, das Wörterbuch an die Threads zu übergeben, die es als regulären Verweis anstelle eines Singletons verwenden, um festzustellen, ob das Problem in der Gemeinsamkeit oder in der Singletonität des Wörterbuchs liegt. (Beseitigung der möglichen Ursachen.)
Ich würde auch versuchen, mit einem
ConcurrentDictionary
anstelle eines regulärenDictionary
nur für den Fall, dass seine Verwendung einige überraschende Ergebnisse liefert. Es gibt viel zu spekulieren über das vorliegende Problem, wennConcurrentDictionary
sich herausstellt, dass eine viel bessere oder viel schlechtere Leistung als Ihre normale erbringtDictionary
.Wenn keiner der oben genannten Punkte auf das Problem hinweist, dann würde ich vermuten, dass die verschlechterte Leistung durch eine seltsame Art von Konflikt zwischen dem müllsammelnden Thread und dem Rest Ihrer Threads verursacht wird, während der Müllsammler versucht, herauszufinden, ob Die Objekte in Ihrem Wörterbuch müssen entsorgt werden oder nicht, während Ihre Threads auf sie zugreifen.
quelle