¿Alguien ha usado alguna vez stackalloc
mientras programaba en C #? Soy consciente de lo que hace, pero la única vez que aparece en mi código es por accidente, porque Intellisense lo sugiere cuando empiezo a escribir static
, por ejemplo.
Aunque no está relacionado con los escenarios de uso de stackalloc
, en realidad hago una cantidad considerable de interoperabilidad heredada en mis aplicaciones, por lo que de vez en cuando podría recurrir al uso del unsafe
código. Pero, sin embargo, generalmente encuentro formas de evitar por unsafe
completo.
Y dado que el tamaño de la pila para un solo hilo en .Net es ~ 1Mb (corrígeme si me equivoco), estoy aún más reservado de usar stackalloc
.
¿Hay algunos casos prácticos en los que uno podría decir: "esta es exactamente la cantidad correcta de datos y procesamiento para que no sea seguro y lo use stackalloc
"?
fuente
System.Numbers
utiliza una gran cantidad referencesource.microsoft.com/#mscorlib/system/...Respuestas:
La única razón para usar
stackalloc
es el rendimiento (ya sea para cálculos o interoperabilidad). Al usar enstackalloc
lugar de una matriz asignada de almacenamiento dinámico, crea menos presión de GC (la GC necesita ejecutarse menos), no necesita fijar las matrices, es más rápido asignar que una matriz de almacenamiento dinámico, y se libera automáticamente en el método salir (las matrices de montón asignadas solo se desasignan cuando se ejecuta GC). Además, al usar enstackalloc
lugar de un asignador nativo (como malloc o el equivalente .Net), también gana velocidad y desasignación automática al salir del alcance.En cuanto al rendimiento, si lo usa
stackalloc
, aumentará enormemente la posibilidad de que la CPU tenga aciertos en la memoria caché debido a la localidad de los datos.fuente
He usado stackalloc para asignar buffers para el trabajo DSP [casi] en tiempo real. Fue un caso muy específico en el que el rendimiento debía ser lo más consistente posible. Tenga en cuenta que hay una diferencia entre la consistencia y el rendimiento general: en este caso, no me preocupaba que las asignaciones de montón fueran demasiado lentas, solo con el no determinismo de la recolección de basura en ese punto del programa. No lo usaría en el 99% de los casos.
fuente
stackalloc
solo es relevante para el código inseguro. Para el código administrado, no puede decidir dónde asignar los datos. Los tipos de valor se asignan en la pila por defecto (a menos que sean parte de un tipo de referencia, en cuyo caso se asignan en el montón). Los tipos de referencia se asignan en el montón.El tamaño de pila predeterminado para una aplicación .NET simple vainilla es de 1 MB, pero puede cambiar esto en el encabezado PE. Si está iniciando hilos explícitamente, también puede establecer un tamaño diferente a través de la sobrecarga del constructor. Para las aplicaciones ASP.NET, el tamaño de pila predeterminado es de solo 256K, que es algo a tener en cuenta si cambia entre los dos entornos.
fuente
Stackalloc inicialización de tramos. En versiones anteriores de C #, el resultado de stackalloc solo podía almacenarse en una variable local de puntero. A partir de C # 7.2, stackalloc ahora se puede usar como parte de una expresión y puede apuntar a un intervalo, y eso se puede hacer sin usar la palabra clave insegura. Por lo tanto, en lugar de escribir
Puedes escribir simplemente:
Esto también es extremadamente útil en situaciones en las que necesita algo de espacio reutilizable para realizar una operación, pero desea evitar asignar memoria de almacenamiento dinámico para tamaños relativamente pequeños
Fuente: C # - Todo sobre Span: Explorando un nuevo pilar de .NET
fuente
Span
lamentablemente no está disponible en .NET Framework 4.7.2 e incluso no en 4.8 ... Por lo tanto, la nueva función de lenguaje todavía es de uso limitado por el momento.Hay algunas respuestas geniales en esta pregunta, pero solo quiero señalar que
Stackalloc también se puede usar para llamar a API nativas
Muchas funciones nativas requieren que la persona que llama asigne un búfer para obtener el resultado de retorno. Por ejemplo, la función CfGetPlaceholderInfo
cfapi.h
tiene la siguiente firma.Para llamarlo en C # a través de interoperabilidad,
Puedes hacer uso de stackalloc.
fuente