¿Es Interlocked.Increment(ref x)
más rápido o más lento que x++
para ints y longs en varias plataformas?Desempeño del enclavamiento.Incremento
Respuesta
Es más lento ya que fuerza la acción a ocurrir atómicamente y actúa como una barrera de memoria, eliminando la capacidad del procesador para reordenar la memoria accesos alrededor de la instrucción.
Debe usar Interlocked.Increment cuando desee que la acción sea atómica en el estado que se puede compartir entre subprocesos; no se pretende que sea un reemplazo completo para x ++.
Siempre será más lento porque tiene que realizar un bloqueo de bus de CPU frente a simplemente actualizar un registro. Sin embargo, las CPU modernas alcanzan un rendimiento cercano al registro, por lo que es insignificante incluso en el procesamiento en tiempo real.
Mientras que la CPU X86 realiza un buslock durante las operaciones de interbloqueo, todas las CPU que proporcionan operaciones de enclavamiento no requieren un buslock. Algunas CPU tienen la capacidad de señalar que han reservado una única línea de caché y pueden realizar operaciones entrelazadas en esa línea de caché sin un busbloqueo. – Adisak
Es más lento. Sin embargo, es la forma general más eficiente que conozco para lograr seguridad de subprocesos en variables escalares.
'volátil 'es más eficiente en escalares, pero tiene la desventaja de requerir buenas prácticas de codificación para ser utilizado bien. – Abel
cuidado con volátil; algunas arquitecturas de procesador (x86/x64) tienen la capacidad de reordenar accesos a la memoria, independientemente de si esa memoria fue marcada como volátil para el compilador. –
Piénselo un momento y se dará cuenta de que una llamada Increment
no puede ser más rápida que una simple aplicación del operador de incremento. Si lo fuera, entonces la implementación del operador de incremento del compilador llamaría internamente al Increment
, y ellos realizarían lo mismo.
Pero, como puede ver probándolo usted mismo, no realizan lo mismo.
Las dos opciones tienen diferentes propósitos. Use el operador de incremento en general. Use Increment
cuando necesite que la operación sea atómica y está seguro de que todos los demás usuarios de esa variable también están usando operaciones interconectadas. (Si no todos cooperan, entonces realmente no ayuda.)
No, no lo haría - Interbloqueado. No se puede invocar el ingreso en una propiedad, mientras que el operador ++ puede hacerlo. Por lo tanto, ++ no podría llamarlo. – SLaks
Para ser más precisos, Increment toma una referencia int (o larga); ++ toma un int (o largo) no ref ( – SLaks
) El compilador ciertamente podría implementar ++ vía Increment. No se implementaría con una simple instrucción de "llamada", pero podría hacerse usando un temporal introducido por el compilador. El punto es que el compilador usa el método de ayuno disponible para incrementar un número; si hubiera algo más rápido, el compilador lo habría usado en su lugar. –
En nuestra experiencia, InterlockedIncrement() et al en Windows son impactos bastante significativos. En un caso de muestra, pudimos eliminar el enclavamiento y usar ++/- en su lugar. Esto solo redujo el tiempo de ejecución de 140 segundos a 110 segundos. Mi análisis es que el enclavamiento obliga a una ida y vuelta de memoria (de lo contrario, ¿cómo podrían verlo otros núcleos?). Una lectura/escritura de caché L1 es de alrededor de 10 ciclos de reloj, pero una lectura/escritura de memoria es más parecida a 100.
En este caso de ejemplo, calculé el número de operaciones de incremento/disminución en aproximadamente mil millones. Entonces en una CPU de 2Ghz esto es algo así como 5 segundos para el ++/-, y 50 segundos para el enclavamiento. Extiende la diferencia en varios hilos, y está cerca de 30 segundos.
Micrsoft dice: InterlockedIncrement se midió tomando 36-90 ciclos en http://msdn.microsoft.com/en-us/library/windows/desktop/ee418650(v=vs.85).aspx – Lothar
36 suena bien para no disputado operación, estoy midiendo unas 120 veces para una operación muy controvertida en un Core i7, pero tal vez lo fallé? De todos modos, "el enclavamiento obliga a una ida y vuelta de memoria (de lo contrario, ¿cómo podrían verlo otros núcleos?). Una lectura/escritura de caché L1 es de alrededor de 10 ciclos de reloj ...": basta marcar esa página como modificada y solo vaciar de L1 a la memoria si otro núcleo necesita verlo, entonces la operación no impugnada puede estar más cerca del extremo 10 del espectro (en 36) en lugar de 100 + ... –
Mi prueba del perfomance:
volátil: 65174400
bloqueo: 62428600
entrelazados: 113.248.900
TimeSpan span = TimeSpan.FromSeconds(5);
object syncRoot = new object();
long test = long.MinValue;
Do(span, "volatile",() => {
long r = Thread.VolatileRead(ref test);
r++;
Thread.VolatileWrite(ref test, r);
});
Do(span, "lock",() =>
{
lock (syncRoot)
{
test++;
}
});
Do(span, "interlocked",() =>
{
Interlocked.Increment(ref test);
});
¿Qué es 'Hacer'? – SLaks
Se ejecuta el método n veces hasta que se haya alcanzado el intervalo de tiempo – MastsrOfDesaster
Entonces, espere, ¿hay algo mejor en este caso? ¿Podría especificar cuáles son sus métricas? –
- 1. JavaScript Evaluación del Desempeño
- 2. ¿Desempeño dinámico del lenguaje .NET?
- 3. desempeño agregado
- 4. Scala pregunta de desempeño
- 5. Desempeño del despachador de WPF (100-200 actualizaciones/seg)
- 6. jQuery UI diálogo alrededor del iframe; ¿problemas de desempeño?
- 7. "listas enlazadas" Mathematica y desempeño
- 8. Desempeño de terracota y consejos
- 9. Desempeño de la aplicación WPF
- 10. ¿Desempeño de StringBuilder en C#?
- 11. Desempeño de ensamblados .NET ILMerged
- 12. ¿Desempeño de las funciones de MySql Xml?
- 13. MySQL filas de recuento de desempeño anteriores
- 14. Java para pregunta de desempeño bucle
- 15. Desempeño de WCF, latencia y escalabilidad
- 16. PHP array ¿copiar ciertas teclas, funciones integradas? ¿Desempeño anidado del bucle?
- 17. En el desempeño de la función `first` de Clojure
- 18. Desempeño de operaciones enteras y en bits en la GPU
- 19. Desempeño de SOAP frente a XML-RPC o RESTO
- 20. Desempeño de almacenamiento de tablas Azure: REST vs. StorageClient
- 21. Desempeño deficiente de las herramientas de descompresión de Java
- 22. servidor SQL unirse vs pregunta de desempeño subconsulta
- 23. Optimizando el desempeño de Put en Berkeley DB
- 24. Android Map ¿Desempeño pobre debido a muchas superposiciones?
- 25. ¿Desempeño de configuración de img src a valor sin cambios?
- 26. Java: Desempeño de Enumerados contra if-then-else
- 27. ¿Desempeño de consultas en dos bases de datos mysql en el mismo servidor?
- 28. Desempeño de sistemas grandes de EAV/esquema abierto en SQL Server
- 29. Mejor Marco Orientado a los Aspectos para características/desempeño de compilación en .net
- 30. Desempeño de WPF: mostrar miles de rutas/formas en un lienzo
Como otros señalan, no es lo mismo. Dicho esto, de acuerdo con http://msdn.microsoft.com/en-us/magazine/cc163726.aspx un enclavamiento.Incremento toma unos 14nS (o aproximadamente 71'000'000 por segundo) por lo que no me preocuparía mucho sobre el rendimiento – smirkingman
Interlocked.Increment está diseñado para ser utilizado en entornos de subprocesos – EProgrammerNotFound