He estado trabajando bajo el principio de compartir nada de la programación concurrente. Esencialmente, todos mis hilos de trabajo tienen copias inmutables de solo lectura del mismo estado que nunca se comparte entre ellos ( incluso por referencia ). En términos generales, esto ha funcionado realmente bien.
Ahora, alguien ha introducido un caché singleton sin bloqueo ( por ejemplo, un diccionario estático ) al que todos los hilos están accediendo simultáneamente. Como el diccionario nunca se modifica después del inicio, no hay bloqueos. No ha habido problemas de seguridad de subprocesos, pero ahora hay una degradación del rendimiento.
La pregunta es ... dado que no hay bloqueos, ¿por qué la introducción de este singleton crea un éxito en el rendimiento? ¿Qué está sucediendo exactamente debajo de las sábanas que podría explicar esto?
Para confirmar, acceder a este nuevo singleton es el único cambio y puedo recrearlo de manera confiable simplemente comentando la llamada al caché.
fuente
Respuestas:
Podría ser que el estado inmutable comparte una línea de caché con algo mutable. En este caso, un cambio en el estado mutable cercano podría tener el efecto de forzar una resincronización de esta línea de caché en los núcleos, lo que podría ralentizar el rendimiento.
fuente
false sharing
escenario que estás describiendo. Para aislar eso, necesitaré perfilar el caché L2. Desafortunadamente, estos son tipos de referencia, por lo que agregar espacio de búfer no será una opción si esto es realmente lo que está sucediendo.Me aseguraría de que los métodos
Equals()
yGetHashCode()
de los objetos que utiliza como claves para el diccionario no tengan ningún efecto secundario inesperado que no sea compatible con subprocesos. Perfilar sería de gran ayuda aquí.Si por casualidad sus claves son cadenas, entonces tal vez ahí lo tenga: se rumorea que las cadenas se comportan como objetos inmutables, pero en aras de ciertas optimizaciones, se implementan internamente de manera mutable, con todo lo que esto implica con respecto al subprocesamiento múltiple .
Intentaría pasar el diccionario a los hilos que lo usan como referencia regular en lugar de un solo tono para ver si el problema radica en la compartición o en el tono único del diccionario. (Eliminando las posibles causas).
También trataría con un en
ConcurrentDictionary
lugar de un regularDictionary
solo en caso de que su uso arroje algunos resultados sorprendentes. Hay muchas cosas que se deben especular sobre el problema en cuestión si unConcurrentDictionary
resultado es mucho mejor o peor que el habitualDictionary
.Si ninguno de los puntos anteriores apunta al problema, entonces supongo que el rendimiento degradado es causado por algún tipo de disputa extraña entre el hilo de recolección de basura y el resto de sus hilos, ya que el recolector de basura está tratando de averiguar si los objetos en su diccionario deben ser eliminados o no, mientras sus hilos están accediendo a ellos.
fuente