Pracowałem zgodnie z zasadą równoczesnego programowania bez udziału. Zasadniczo wszystkie moje wątki robocze mają niezmienne kopie tylko do odczytu tego samego stanu, które nigdy nie są udostępniane między nimi ( nawet przez odniesienie ). Ogólnie rzecz biorąc, działało to naprawdę dobrze.
Teraz ktoś wprowadził bufor singleton bez blokady ( np. Słownik statyczny ), do którego jednocześnie uzyskują dostęp wszystkie wątki. Ponieważ słownik nigdy nie jest zmieniany po uruchomieniu, nie ma blokad. Nie wystąpiły żadne problemy z bezpieczeństwem wątków, ale teraz nastąpił spadek wydajności.
Pytanie brzmi ... skoro nie ma żadnych blokad, dlaczego wprowadzenie tego singletonu tworzy hit? Co dokładnie dzieje się pod przykrywkami, które mogłyby to wyjaśnić?
Aby to potwierdzić, dostęp do tego nowego singletonu jest jedyną zmianą i mogę go wiarygodnie odtworzyć, po prostu komentując połączenie z pamięcią podręczną.
źródło
Odpowiedzi:
Możliwe, że stan niezmienny dzieli linię bufora z czymś zmiennym. W takim przypadku zmiana pobliskiego stanu zmiennego może spowodować wymuszenie ponownej synchronizacji tej linii pamięci podręcznej na rdzeniach, co może spowolnić wydajność.
źródło
false sharing
scenariusz, który opisujesz. Aby to wyodrębnić, muszę profilować pamięć podręczną L2. Niestety, są to typy referencyjne, więc dodanie przestrzeni buforowej nie będzie możliwe, jeśli tak właśnie się dzieje.Upewniłbym się, że metody
Equals()
iGetHashCode()
obiektów, których używasz jako kluczy do słownika, nie powodują żadnych nieoczekiwanych efektów ubocznych nieprzyjaznych wątkom. Profilowanie bardzo by tu pomogło.Jeśli przez przypadek twoje klucze są ciągami, to być może masz je: plotka głosi, że ciągi zachowują się jak niezmienne obiekty, ale ze względu na pewne optymalizacje są one implementowane wewnętrznie w sposób zmienny, ze wszystkim, co wiąże się to z wielowątkowością .
Spróbowałbym przekazać słownik do wątków, które używają go jako zwykłego odniesienia zamiast singletonu, aby sprawdzić, czy problem leży w udostępnianiu, czy w singletonowości słownika. (Eliminacja możliwych przyczyn.)
Spróbowałbym również
ConcurrentDictionary
zamiast zwykłegoDictionary
na wypadek, gdyby jego użycie przyniosło zaskakujące rezultaty. Jest wiele rzeczy do spekulacji na temat problemu, jeśliConcurrentDictionary
okaże się, że działa znacznie lepiej lub znacznie gorzej niż zwykleDictionary
.Jeśli żadne z powyższych nie wskazuje na problem, zgaduję, że obniżona wydajność jest spowodowana dziwnym sporem między wątkiem zbierającym śmieci a resztą twoich wątków, ponieważ śmieciarz próbuje dowiedzieć się, czy obiekty w twoim słowniku muszą zostać usunięte lub nie, podczas gdy są dostępne dla twoich wątków.
źródło