Pregunta

nos encontramos con problemas de rendimiento, y un posible culpable es el uso centralizado de un singleton volátil. el código específico tiene la forma

class foo {
  static volatile instance;
  static object l = new object();

  public static foo Instance {
    if (instance == null)
      lock(l) {
        if (instance == null)
          instance = new foo();
      }

    return foo();
  }
}

esto se está ejecutando en una caja de 8 vías, y estamos viendo un cambio de contexto de 500,000 por segundo. los recursos típicos del sistema están bien: 25% de uso de CPU, 25% de uso de memoria, bajo IO, sin paginación, etc.

¿el uso de un campo volátil induce una barrera de memoria o algún tipo de recarga de caché de la CPU? ¿o solo va después de la memoria principal cada vez, solo para ese campo?

¿Fue útil?

Solución

lock induce una barrera de memoria, por lo que si siempre está accediendo a la instancia en un bloqueo, no necesita el volátil.

Según esto sitio :

  

La palabra clave volátil C # implementa adquirir y liberar semántica, lo que implica una barrera de memoria de lectura en lectura y una barrera de memoria de escritura en escritura.

Otros consejos

Una cosa que volátil no hará es causar un cambio de contexto. Si está viendo 500,000 cambios de contexto por segundo, significa que sus hilos están bloqueando algo y volátil es no el culpable.

Lamentablemente, el singleton tiene una mala reputación por casi todo :)

Este no es mi dominio de experiencia, pero que yo sepa, no hay nada especial sobre volátil aparte del compilador / tiempo de ejecución que NO reordena las lecturas / escrituras (a la variable) para fines de optimización.

Editar: estoy corregido. La volatilidad no solo introduce barreras de memoria, sino que lo que sucede (y, por cierto, el rendimiento) depende en gran medida de la CPU particular involucrada. Ver http://dotnetframeworkplanet.blogspot.com /2008/11/volatile-field-and-memory-barrier-look.html

Es por eso que todavía necesita el bloqueo.

Preguntas que pueden o no haber sido respondidas ya:

  1. ¿Qué está haciendo realmente tu instancia de singleton? Tal vez el código de instancia necesita ser refactorizado ...
  2. ¿Cuál es el número de hilos del proceso en ejecución? Un cuadro de 8 vías no te ayudará si tienes un número de hilos anormalmente alto.
  3. Si es más alto de lo esperado, ¿por qué?
  4. ¿Qué más se está ejecutando en el sistema?
  5. ¿Es consistente el problema de rendimiento?

En su ejemplo aquí, la volatilidad no debe ser objeto de ninguna "desaceleración". Sin embargo, el bloqueo () puede implicar grandes viajes de ida y vuelta al núcleo, especialmente si hay mucha contención para el bloqueo.

Realmente no hay necesidad de bloquear su singleton en este caso, podría simplemente hacer

class Foo {
  static Foo instance = new Foo();
  public static Foo FooInstance() {
    return instance ;
  }
}

Por supuesto, si 'instancia' se usa en muchos hilos diferentes, aún tendría que bloquear () cualquier cosa que altere ese Foo, a menos que todos los métodos / propiedades de Foo sean de solo lectura. por ejemplo,

 class Foo {
      static Foo instance = new Foo();
      object l = new object();
      int doesntChange = 42;
      int canChange = 123;
      public static Foo FooInstance() {
        return instance ;
      }
      public void Update(int newVal) {
         lock(l) { // you'll get a lot of trouble without this lock if several threads accesses the same FOO. Atleast if they later on read that variable 
            canChange = newVal;
         }

      public int GetFixedVal() {
         return doesntChange; //no need for a lock. the doesntChange is effectivly read only
      }
    }

Realmente no hay necesidad del uso de volátiles para un singleton, ya que lo configura exactamente una vez y bloquea el código que lo configura. Consulte el artículo de Jon Skeet sobre singletons para obtener más información.

La respuesta corta es: Sí, crea una barrera de memoria (vacía todo y va a la memoria principal, no solo a esa variable única), pero No, no será la causa del cambio de contexto.

Además, como otros han mencionado, no creo que sea necesario volátil aquí.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top