una son que programacion pilas pila lifo estatica eliminar elemento ejemplo como colas cola ats c# stack clr stack-size

c# - programacion - que son pilas en c



¿Por qué el tamaño de la pila en C#es exactamente 1 MB? (2)

El enlazador especifica el tamaño predeterminado de la pila reservada y los desarrolladores pueden anularlo cambiando el valor de PE en el momento del enlace o para un subproceso individual especificando el parámetro dwStackSize para la función CreateThread WinAPI.

Si crea un hilo con el tamaño de pila inicial mayor o igual al tamaño de pila predeterminado, entonces se redondea al múltiplo más cercano de 1 MB.

¿Por qué el valor es igual a 1 MB para procesos de 32 bits y 4 MB para 64 bits? Creo que debería preguntar a los desarrolladores, quienes diseñaron Windows, o esperar hasta que alguien responda su pregunta.

Probablemente Mark Russinovich lo sabe y puedes contact . Tal vez pueda encontrar esta información en sus libros de Windows Internals anteriores a la sexta edición, que describe menos información sobre las pilas en lugar de su article . O tal vez Raymond Chen conoce las razones, ya que escribe cosas interesantes sobre las partes internas de Windows y su historia. Él también puede responder a su pregunta, pero debe publicar una sugerencia en el Buzón de sugerencias .

Pero en este momento trataré de explicar algunas razones probables por las cuales Microsoft ha elegido estos valores usando los blogs de MSDN, Mark y Raymond.

Los valores predeterminados tienen estos valores probablemente porque en los primeros tiempos las PC eran lentas y la asignación de memoria en la pila era mucho más rápida que la asignación de memoria en el montón. Y dado que las asignaciones de pila eran mucho más baratas, se usaban, pero requería un tamaño de pila más grande.

Por lo tanto, el valor era el tamaño óptimo de pila reservada para la mayoría de las aplicaciones. Es óptimo porque permite hacer muchas llamadas anidadas y asignar memoria en la pila para pasar estructuras a funciones de llamada. Al mismo tiempo, permite crear muchos hilos.

Hoy en día, estos valores se utilizan principalmente para la compatibilidad con versiones anteriores, porque las estructuras que se pasan como parámetros a las funciones de WinAPI todavía se asignan en la pila. Pero si no está utilizando asignaciones de pila, el uso de la pila de un hilo será significativamente menor que el valor predeterminado de 1 MB y es un desperdicio, como mencionó Hans Passant. Y para evitar esto, el sistema operativo confirma solo la primera página de la pila (4 KB), si no se especifica otra en el encabezado PE de la aplicación. Otras páginas se asignan a pedido.

Algunas aplicaciones anulan el espacio de direcciones reservado y se comprometieron inicialmente a optimizar el uso de la memoria. Como ejemplo, el tamaño máximo de pila de un hilo del proceso nativo de IIS es de 256 KB ( KB932909 ). Y Microsoft recommended esta disminución de los valores predeterminados:

Es mejor elegir un tamaño de pila tan pequeño como sea posible y confirmar la pila necesaria para que el hilo o la fibra funcionen de manera confiable. Cada página reservada para la pila no se puede utilizar para ningún otro propósito.

Fuentes:

  1. recommended
  2. article
  3. KB932909

Las PC de hoy en día tienen una gran cantidad de RAM física, pero aún así, el tamaño de la pila de C # es de solo 1 MB para procesos de 32 bits y 4 MB para procesos de 64 bits ( capacidad de pila en C # ).

¿Por qué el tamaño de la pila en CLR sigue siendo tan limitado?

¿Y por qué es exactamente 1 MB (4 MB) (y no 2 MB o 512 KB)? ¿Por qué se decidió usar estas cantidades?

Estoy interesado en consideraciones y razones detrás de esa decisión .


Estás mirando al tipo que tomó esa decisión. David Cutler y su equipo seleccionaron un megabyte como tamaño de pila predeterminado. Nada que ver con .NET o C #, esto se concretó cuando crearon Windows NT. Un megabyte es lo que elige cuando el encabezado EXE de un programa o la llamada winapi CreateThread () no especifica explícitamente el tamaño de la pila. Cuál es la forma normal, casi cualquier programador deja el sistema operativo para elegir el tamaño.

Esa elección probablemente sea anterior al diseño de Windows NT, la historia es demasiado turbia al respecto. Sería bueno que Cutler escribiera un libro al respecto, pero nunca ha sido escritor. Ha sido extraordinariamente influyente en la forma en que funcionan las computadoras. Su primer diseño de sistema operativo fue RSX-11M, un sistema operativo de 16 bits para computadoras DEC (Digital Equipment Corporation). Influyó fuertemente en el CP / M de Gary Kildall, el primer sistema operativo decente para microprocesadores de 8 bits. Lo que influyó mucho en MS-DOS.

Su siguiente diseño fue VMS, un sistema operativo para procesadores de 32 bits con soporte de memoria virtual. Muy exitoso. El siguiente fue cancelado por DEC en el momento en que la compañía comenzó a desintegrarse, no pudiendo competir con hardware de PC barato. Ante Microsoft, le hicieron una oferta que no pudo rechazar. Muchos de sus compañeros de trabajo se unieron también. Trabajaron en VMS v2, mejor conocido como Windows NT. DEC se molestó por eso, el dinero cambió de manos para resolverlo. Si VMS ya eligió un megabyte es algo que no sé, solo conozco el RSX-11 lo suficientemente bien. No es improbable.

Suficiente historia. Un megabyte es mucho , un hilo real rara vez consume más de un par de puñados de kilobytes. Por lo tanto, un megabyte es realmente un desperdicio. Sin embargo, es el tipo de desperdicio que puede permitirse en un sistema operativo de memoria virtual paginado por demanda, ese megabyte es solo memoria virtual . Solo números para el procesador, uno por cada 4096 bytes. En realidad, nunca usa la memoria física, la RAM en la máquina, hasta que realmente la aborde.

Es excesivo en un programa .NET porque el tamaño de un megabyte se eligió originalmente para acomodar programas nativos. Que tienden a crear grandes marcos de pila, almacenando cadenas y buffers (matrices) en la pila también. Infame por ser un vector de ataque de malware, un desbordamiento de búfer puede manipular el programa con datos. No es la forma en que funcionan los programas .NET, las cadenas y las matrices se asignan en el montón de GC y se verifica la indexación. La única forma de asignar espacio en la pila con C # es con la palabra clave stackalloc insegura.

El único uso no trivial de la pila en .NET es por jitter. Utiliza la pila de su hilo para compilar MSIL justo a tiempo para codificar la máquina. Nunca he visto ni comprobado cuánto espacio requiere, sino que depende de la naturaleza del código y de si el optimizador está habilitado o no, pero un par de decenas de kilobytes es una suposición aproximada. De lo contrario, cómo este sitio web obtuvo su nombre, un desbordamiento de pila en un programa .NET es bastante fatal. No queda suficiente espacio (menos de 3 kilobytes) para JITAR de manera confiable cualquier código que intente detectar la excepción. Kaboom para escritorio es la única opción.

Por último, pero no menos importante, un programa .NET hace algo bastante improductivo con la pila. El CLR confirmará la pila de un hilo. Esa es una palabra costosa que significa que no solo reserva el tamaño de la pila, sino que también se asegura de que el espacio esté reservado en el archivo de paginación del sistema operativo para que la pila siempre se pueda cambiar cuando sea necesario. No confirmar es un error fatal y finaliza un programa incondicionalmente. Eso solo sucede en una máquina con muy poca RAM que ejecuta demasiados procesos, tal máquina habrá recurrido a la melaza antes de que los programas comiencen a morir. Un posible problema hace más de 15 años, no hoy. Los programadores que ajustan su programa para actuar como un auto de carreras F1 usan el elemento <disableCommitThreadStack> en su archivo .config.

Fwiw, Cutler no dejó de diseñar sistemas operativos. Esa foto se hizo mientras trabajaba en Azure.

Actualización, noté que .NET ya no confirma la pila. No estoy exactamente seguro de cuándo o por qué sucedió esto, ha pasado demasiado tiempo desde que lo revisé. Supongo que este cambio de diseño ocurrió en algún lugar alrededor de .NET 4.5. Cambio bastante sensato.