¿Qué tiene de malo usar GC.Collect ()?

103

Aunque entiendo las serias implicaciones de jugar con esta función (o al menos eso es lo que creo), no veo por qué se está convirtiendo en una de estas cosas que los programadores respetables nunca usarían, incluso aquellos que ni siquiera saben para qué sirve.

Digamos que estoy desarrollando una aplicación en la que el uso de la memoria varía enormemente según lo que esté haciendo el usuario. El ciclo de vida de la aplicación se puede dividir en dos etapas principales: edición y procesamiento en tiempo real. Durante la etapa de edición, suponga que se crean miles de millones o incluso billones de objetos; algunos de ellos pequeños y otros no, algunos pueden tener finalizadores y otros no, y suponen que su vida útil varía desde unos pocos milisegundos hasta largas horas. A continuación, el usuario decide cambiar a la etapa de tiempo real. En este punto, suponga que el desempeño juega un papel fundamental y la más mínima alteración en el flujo del programa podría traer consecuencias catastróficas. La creación de objetos se reduce al mínimo posible mediante el uso de grupos de objetos y todo eso, pero luego, el GC interviene inesperadamente y lo tira todo, y alguien muere.

La pregunta: En este caso, ¿no sería prudente llamar a GC.Collect () antes de ingresar a la segunda etapa?

Después de todo, estas dos etapas nunca se superponen en el tiempo entre sí y toda la optimización y las estadísticas que el GC podría haber recopilado serían de poca utilidad aquí ...

Nota: Como algunos de ustedes han señalado, .NET podría no ser la mejor plataforma para una aplicación como esta, pero eso está más allá del alcance de esta pregunta. La intención es aclarar si una llamada GC.Collect () puede mejorar el comportamiento / rendimiento general de una aplicación o no. Todos estamos de acuerdo en que las circunstancias bajo las cuales harías tal cosa son extremadamente raras pero, de nuevo, el GC intenta adivinar y lo hace perfectamente bien la mayor parte del tiempo, pero aún se trata de adivinar.

Gracias.

9 revoluciones
fuente
24
"la más mínima alteración en el flujo del programa podría traer consecuencias catastróficas ... alguien podría morir" - ¿está seguro de que C # .NET es suficientemente determinista para sus propósitos?
Steve Jessop
4
Ni Windows ni .NET son plataformas en tiempo real y, por lo tanto, no se pueden garantizar métricas de rendimiento, al menos no lo suficiente como para arriesgar vidas humanas. Estoy de acuerdo con uno por uno en que o está exagerando o es descuidado.
Sergio Acosta
3
LOL en "una de estas cosas que los programadores respetables nunca usarían, incluso aquellos que ni siquiera saben para qué sirve". Los programadores que usan cosas sin saber por qué no son los más respetables en mi libro. :)
The Dag

Respuestas:

87

Del Blog de Rico ...

Regla 1

No lo hagas.

Esta es realmente la regla más importante. Es justo decir que la mayoría de los usos de GC.Collect () son una mala idea y entré en eso con cierto detalle en la publicación original, por lo que no repetiré todo eso aquí. Así que pasemos a ...

Regla # 2

Considere llamar a GC.Collect () si acaba de ocurrir algún evento no recurrente y es muy probable que este evento haya causado la muerte de muchos objetos antiguos.

Un ejemplo clásico de esto es si está escribiendo una aplicación cliente y muestra un formulario muy grande y complicado que tiene muchos datos asociados. Su usuario acaba de interactuar con este formulario creando potencialmente algunos objetos grandes ... cosas como documentos XML o un conjunto de datos grande o dos. Cuando el formulario se cierra, estos objetos están muertos y, por lo tanto, GC.Collect () recuperará la memoria asociada con ellos ...

Entonces, parece que esta situación puede caer bajo la Regla n. ° 2, usted sabe que hay un momento en el tiempo en el que muchos objetos viejos han muerto y no es recurrente. Sin embargo, no olvide las palabras de despedida de Rico.

La regla # 1 debería prevalecer sobre la regla # 2 sin evidencia sólida.

Mide, mide, mide.

Jon Norton
fuente
9
Yo diría que esto es solo lo viejo. Nada es realmente malo o peligroso si sabe lo que está haciendo y, por lo tanto, sabe cuándo y cómo hacerlo, así como sus efectos secundarios. Cosas como nunca, nunca uses xxxx se ponen ahí para proteger al mundo de pésimos programadores: D
Jorge Córdoba
ver también stackoverflow.com/questions/233596/…
Ian Ringrose
No estoy diciendo que usar GC.Collect sea una buena práctica. Pero a veces es una forma rápida de resolver problemas sin conocer su causa real. Es feo, lo sé, pero funciona, y me parece que no es un mal enfoque, especialmente cuando no hay mucho tiempo para descubrir la causa raíz del problema y su jefe está detrás de usted ... ya sabe.
Silent Sojourner
58

Si llama a GC.Collect () en el código de producción, esencialmente está declarando que sabe más que los autores del GC. Ese puede ser el caso. Sin embargo, por lo general no lo es y, por lo tanto, se desaconseja enfáticamente.

Aaron Fischer
fuente
3
Eso es muy cierto, pero no sé si podrían hacer suposiciones que se apliquen a todos los desarrollos.
MasterMastic
2
@Ken No, no pueden. ¿Pero estás en una mejor posición para hacerlo? ¿O va a escribir código asumiendo un hardware específico, una versión específica del sistema operativo, etc.? La relación dolor / ganancia es demasiado alta en este caso.
The Dag
2
@TheDag En mi opinión, por supuesto que sí. Cuando estoy liberando memoria y todo eso, realmente no me importa el hardware porque ese es el trabajo del sistema operativo para lidiar con eso. Tampoco me importa el sistema operativo porque tengo una interfaz común a todos los que estoy programando. (por ejemplo, no me importa si es Windows, Mac o Linux: cuando estoy asignando / liberando memoria en C / C ++ es nuevo / elimino malloc / dealloc). Siempre podría estar equivocado, así que siéntete libre de corregirme.
MasterMastic
@MasterMastic mallocsolo tiene una interfaz muy simple, y sus implementaciones pueden variar lo suficiente como para importar. Todo depende del tipo de problema que intente resolver. Si mallocfuera "suficientemente bueno", no necesitaría la agrupación de búfer, ¿verdad? El desarrollo de C / C ++ está lleno de ejemplos en los que intenta adivinar el sistema operativo / tiempo de ejecución / bibliotecas porque lo sabe mejor (y, a veces, realmente lo sabe). Muchas aplicaciones críticas para el rendimiento evitan por completo el uso de asignadores de tiempo de ejecución / sistema. Juegos utilizados para preasignar toda la memoria al inicio (matrices de tamaño constante, etc.).
Luaan
24

Entonces, ¿qué pasa cuando usa objetos COM como MS Word o MS Excel de .NET? Sin llamar GC.Collectdespués de liberar los objetos COM, hemos encontrado que las instancias de la aplicación Word o Excel todavía existen.

De hecho, el código que usamos es:

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

Entonces, ¿sería un uso incorrecto del recolector de basura? Si es así, ¿cómo conseguimos que mueran los objetos de Interop? Además, si no está destinado a usarse así, ¿por quéGC 's Collectmétodo aún Public?

Dib
fuente
3
Esto sería una gran pregunta nueva de StackOverflow, es decir: Cómo erradicar instancias COM sin llamar al GC. Con especial atención a las referencias circulares no gestionadas. Es uno de los desafíos que me hizo desconfiar de actualizar mi complemento VB6 de Outlook a C #. (Hicimos mucho trabajo para desarrollar patrones de codificación y casos de prueba en el lado de VB que garantizaban que las referencias COM se eliminaran de manera determinista cuando ya no se necesitaban).
rkagerer
2
Si esto se aplica a los objetos COM en general, quizás este sea un escenario válido. Pero, desde el principio, diría que el problema es probable que esté utilizando una aplicación cliente diseñada para un escritorio interactivo como servidor COM. De la base de conocimientos de MSDN: "Microsoft actualmente no recomienda ni admite la automatización de aplicaciones de Microsoft Office desde ninguna aplicación o componente cliente desatendido y no interactivo (incluidos ASP, ASP.NET, DCOM y NT Services), porque Office puede exhibir un comportamiento inestable y / o un punto muerto cuando Office se ejecuta en este entorno ".
The Dag
2
@TheDag: es posible que Microsoft no lo recomiende, pero muchos de nosotros hemos tenido que portar el código VB6 antiguo con interoperabilidad de Office a aplicaciones de Windows .Net. Pasé meses de trabajo hasta que finalmente me deshice de todas las referencias colgantes invisibles para un gran proyecto de conversión de VB6 a .Net. Aprender a publicar en orden inverso de asignación y mantener referencias locales a CADA objeto com, incluidas las colecciones, ayudó.
Dib
15

Bueno, la GC es una de esas cosas con las que tengo una relación de amor / odio. Lo hemos roto en el pasado a través de VistaDB y hemos escrito un blog al respecto. Lo han arreglado, pero lleva MUCHO tiempo obtener arreglos de ellos en cosas como esta.

El GC es complejo, y un enfoque único para todos es muy, muy difícil de lograr en algo tan grande. MS ha hecho un trabajo bastante bueno, pero a veces es posible engañar al GC.

En general, no debe agregar a a Collectmenos que sepa con certeza que acaba de deshacerse de una tonelada de memoria y llegará a una crisis de la mediana edad. si el GC no se limpia ahora.

Puede arruinar toda la máquina con una serie de malas GC.Collectdeclaraciones. La necesidad de una declaración de recopilación casi siempre apunta a un error subyacente mayor. La pérdida de memoria generalmente tiene que ver con referencias y una falta de comprensión de cómo funcionan. O usar IDisposableobjetos que no lo necesitan y poner una carga mucho mayor en el GC.

Observe de cerca el% de tiempo dedicado a GC a través de los contadores de rendimiento del sistema. Si ve que su aplicación usa el 20% o más de su tiempo en el GC, tiene problemas graves de administración de objetos (o un patrón de uso anormal). Desea minimizar siempre el tiempo que gasta el GC porque acelerará toda su aplicación.

También es importante tener en cuenta que el GC es diferente en los servidores que en las estaciones de trabajo. He visto una serie de pequeños problemas difíciles de rastrear con personas que no los prueban a ambos (o que ni siquiera saben que hay dos).

Y solo para ser lo más completo posible en mi respuesta, también debe probar en Mono si también está apuntando a esa plataforma. Dado que es una implementación totalmente diferente, puede experimentar problemas totalmente diferentes a los de la implementación de MS.

Jason corto
fuente
El culpable son a menudo los eventos. Siempre que se utiliza un método de instancia como controlador de eventos, el editor del evento tiene una referencia al suscriptor a través del delegado del evento. La única forma "fácil" de evitar problemas de esto es usar solo editores que tengan como mucho la misma duración que los suscriptores (por ejemplo, un TextBox que publica un evento manejado por el formulario contenedor no es un problema, ya que el cuadro de texto no se supone vivir fuera de la forma). Escenario de problema de ejemplo: modelo Singleton, vistas temporales que manejan eventos de modelo.
The Dag
5
¿Cómo se puede estropear toda la máquina?
Adam R. Gray
13

Hay situaciones en las que es útil, pero en general conviene evitarlo. Podrías compararlo con GOTO o con un ciclomotor: lo haces cuando lo necesitas, pero no se lo cuentas a tus amigos.

rjohnston
fuente
12

Desde mi experiencia, nunca ha sido aconsejable realizar una llamada a GC.Collect () en el código de producción. En la depuración, sí, tiene sus ventajas para ayudar a aclarar posibles fugas de memoria. Supongo que mi razón fundamental es que el GC ha sido escrito y optimizado por programadores mucho más inteligentes que yo, y si llego a un punto en el que siento que necesito llamar a GC.Collect () es una pista de que me he salido del camino algun lado. En su situación, no parece que realmente tenga problemas de memoria, solo que le preocupa la inestabilidad que traerá la recopilación a su proceso. Dado que no limpiará los objetos que todavía están en uso y que se adapta muy rápidamente a las demandas tanto crecientes como decrecientes, creo que no tendrá que preocuparse por eso.

TheZenker
fuente
10

Una de las principales razones para llamar a GC.Collect () es cuando acaba de realizar un evento significativo que crea mucha basura, como lo que describe. Llamar a GC.Collect () puede ser una buena idea aquí; de lo contrario, es posible que el CG no comprenda que fue un evento "único".

Por supuesto, debes perfilarlo y verlo por ti mismo.

TraumaPony
fuente
9

Bueno, obviamente, no debería escribir código con requisitos en tiempo real en lenguajes con recolección de basura en tiempo no real.

En un caso con etapas bien definidas, no hay ningún problema con activar el recolector de basura. Pero este caso es extremadamente raro. El problema es que muchos desarrolladores intentarán usar esto para resolver problemas de papel en un estilo de culto a la carga, y agregarlo indiscriminadamente causará problemas de rendimiento.

ruido
fuente
Cierto. Pero las pruebas automatizadas capaces de detectar la condición de error "el objeto no es elegible para la recolección de basura, pero debería serlo" serían valiosas. En este caso, podría lograrse mediante una combinación de lógica de fábrica, lógica de destructor y GC.Collect. Por ejemplo, su clase de entidad tiene una propiedad IObjectTracker, normalmente nula pero asignada por la fábrica de entidades de propósito de prueba. La fábrica también notifica al rastreador del nacimiento del objeto, mientras que el destructor lo notifica (cuando está presente) de la muerte. Si puede saber que "el destructor se ha ejecutado para todos los objetos recolectables de basura", puede verificar el estado del rastreador para detectar fugas.
The Dag
7

Llamar a GC.Collect () obliga a CLR a realizar un recorrido por la pila para ver si cada objeto se puede liberar de verdad comprobando las referencias. Esto afectará la escalabilidad si la cantidad de objetos es alta y también se sabe que activa la recolección de basura con demasiada frecuencia. Confíe en CLR y deje que el recolector de basura se ejecute solo cuando sea apropiado.

Ta01
fuente
2
No solo hace que la pila camine, sino que el subproceso principal de su aplicación (y cualquier subproceso secundario que haya creado) se congelan para que el GC pueda recorrer la pila. Cuanto más tiempo pasa su aplicación en GC, más tiempo pasa congelada.
Scott Dorman
3
Me preocupa más un bloqueo de la aplicación debido a una excepción de memoria insuficiente que un rendimiento lento porque la aplicación / GC estaba tirando cosas que ya no son necesarias. ¿Alguien sabe por qué Microsoft parece lanzar una excepción OOM sin PRIMERO tirar la basura? (Sin este paso OBVIO, o al menos una explicación de por qué este paso no parece ser intentado antes de lanzar la excepción OOM, no estoy seguro de tener fe en que las cosas sucedan "automáticamente" de la "forma en que se supone que deben hacerlo"
Wonderbird
6

De hecho, no creo que sea una mala práctica llamar a GC.Collect.
Puede haber casos en los que lo necesitemos. Solo por ejemplo, tengo un formulario que ejecuta un hilo, que a su vez abre diferentes tablas en una base de datos, extrae el contenido de un campo BLOB a un archivo temporal, cifra el archivo, luego lee el archivo en un flujo binario y de nuevo en un BLOB campo en otra tabla.

Toda la operación requiere bastante memoria y no se sabe con certeza la cantidad de filas y el tamaño del contenido del archivo en las tablas.

Solía ​​obtener la excepción OutofMemory a menudo y pensé que sería prudente ejecutar GC.Collect periódicamente en función de una variable de contador. Incremento un contador y cuando se alcanza un nivel específico, se llama a GC para recolectar cualquier basura que pueda haberse formado y para recuperar cualquier memoria perdida debido a pérdidas de memoria imprevistas.

Después de esto, creo que está funcionando bien, ¡al menos sin excepción!
Llamo de la siguiente manera:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).
Venugopal M
fuente
5

Bajo .net, el tiempo requerido para realizar una recolección de basura está mucho más relacionado con la cantidad de cosas que no son basura que con la cantidad de cosas que lo son. De hecho, a menos que un objeto anule Finalize(ya sea explícitamente o mediante el destructor de C #), sea el objetivo de a WeakReference, se encuentre en el Montón de objetos grandes o sea especial de alguna otra manera relacionada con gc, lo único que identifica la memoria en la que se encuentra como objeto es la existencia de referencias arraigadas a él. De lo contrario, la operación del GC es análoga a tomar de un edificio todo lo que tiene valor y dinamitar el edificio, construir uno nuevo en el sitio del antiguo y poner todos los artículos valiosos en él. El esfuerzo necesario para dinamitar el edificio es totalmente independiente de la cantidad de basura que contenga.

En consecuencia, llamando GC.Collect puede aumentar la cantidad total de trabajo que tiene que hacer el sistema. Retrasará la ocurrencia de la siguiente colección, pero probablemente hará tanto trabajo inmediatamente como lo hubiera requerido la siguiente colección cuando ocurrió; en el momento en que se habría producido la siguiente recolección, la cantidad total de tiempo dedicado a la recolección habrá sido aproximadamente el mismo que GC.Collectno se había llamado, pero el sistema habrá acumulado algo de basura, lo que provocará que la recolección posterior se requiera antes de lo que GC.Collectno se había hecho ha sido llamado.

Los momentos que puedo ver GC.Collectque son realmente útiles son cuando uno necesita medir el uso de memoria de algún código (ya que las cifras de uso de memoria solo son realmente significativas después de una colección), o perfilar cuál de varios algoritmos es mejor (llamando a GC.Collect () antes de ejecutar cada uno de varios fragmentos de código puede ayudar a garantizar un estado de línea de base consistente). Hay algunos otros casos en los que uno puede saber cosas que el GC no sabe, pero a menos que uno esté escribiendo un programa de un solo subproceso, no hay forma de que uno pueda saber que una GC.Collectllamada que ayudaría a las estructuras de datos de un subproceso a evitar la "crisis de la mediana edad "no causaría que los datos de otros subprocesos tuvieran una" crisis de la mediana edad "que de otro modo se habría evitado.

Super gato
fuente
5

Creación de imágenes en un bucle: incluso si llama a dispose, la memoria no se recupera. Recolección de basura cada vez. Pasé de 1,7 GB de memoria en mi aplicación de procesamiento de fotos a 24 MB y el rendimiento es excelente.

Es absolutamente el momento de llamar a GC.Collect.

valle
fuente
2
No Disposese supone que las llamadas liberen la memoria administrada. Parece que no sabe cómo funciona el modelo de memoria en .NET.
Andrew Barber
4

Tuvimos un problema similar con el recolector de basura que no recolectaba basura y liberaba memoria.

En nuestro programa, estábamos procesando algunas hojas de cálculo de Excel de tamaño modesto con OpenXML. Las hojas de cálculo contenían entre 5 y 10 "hojas" con aproximadamente 1000 filas de 14 columnas.

El programa en un entorno de 32 bits (x86) se bloqueaba con un error de "memoria insuficiente". Logramos que se ejecutara en un entorno x64, pero queríamos una solución mejor.

Encontramos uno.

Aquí hay algunos fragmentos de código simplificados de lo que no funcionó y lo que funcionó cuando se trata de llamar explícitamente al recolector de basura para liberar memoria de los objetos desechados.

Llamar al GC desde el interior de la subrutina no funcionó. La memoria nunca fue recuperada ...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

Al mover la llamada de GC fuera del alcance de la subrutina, se recogió la basura y se liberó la memoria.

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

Espero que esto ayude a otros que están frustrados con la recolección de basura .NET cuando parece ignorar las llamadas a GC.Collect().

Paul Smith

Paul Smith
fuente
4

No hay nada de malo en pedir explícitamente una colección. Algunas personas simplemente quieren creer que si es un servicio proporcionado por el proveedor, no lo cuestionen. Ah, ¿y todos esos bloqueos aleatorios en los momentos equivocados de su aplicación interactiva? ¡La próxima versión lo hará mejor!

Dejar que un proceso en segundo plano se ocupe de la manipulación de la memoria significa no tener que lidiar con eso nosotros mismos, es cierto. Pero esto no significa lógicamente que sea mejor para nosotros no lidiar con eso nosotros mismos bajo todas las circunstancias. El GC está optimizado para la mayoría de los casos. Pero esto no significa lógicamente que esté optimizado en todos los casos.

¿Alguna vez ha respondido una pregunta abierta como "cuál es el mejor algoritmo de clasificación" con una respuesta definitiva? Si es así, no toque el GC. Para aquellos de ustedes que pidieron las condiciones, o dieron respuestas tipo 'en este caso', pueden proceder para aprender sobre el GC y cuándo activarlo.

Tengo que decir que he tenido aplicaciones congeladas en Chrome y Firefox que me frustran muchísimo, e incluso entonces, en algunos casos, la memoria crece sin obstáculos, si tan solo aprendieran a llamar al recolector de basura, o me dieran un para que cuando empiece a leer el texto de una página pueda presionarlo y así estar libre de bloqueos durante los próximos 20 minutos.

Gerard ONeill
fuente
2

Creo que tiene razón sobre el escenario, pero no estoy seguro de la API.

Microsoft dice que en tales casos debe agregar presión de memoria como una pista al GC de que pronto debería realizar una recopilación.

Sergio Acosta
fuente
2
Interesante, pero la documentación dice que AddMemoryPressure debe usarse cuando 'un pequeño objeto administrado asigna una gran cantidad de memoria no administrada'. (énfasis mío)
Robert Paulson
2

¿Qué tiene de malo? El hecho de que esté cuestionando el recolector de basura y el asignador de memoria, que entre ellos tienen una idea mucho mayor sobre el uso de memoria real de su aplicación en tiempo de ejecución que usted.

Robar
fuente
1
La naturaleza heurística del recolector de basura y el hecho de que expusieron esta funcionalidad al mundo exterior me hacen pensar en ella como algo que es útil si se usa donde debe estar. El problema no es usarlo sino saber cómo, dónde y cuándo usarlo.
Trampa
Sin mencionar el mejor conocimiento de los GC sobre todas las demás aplicaciones y sus necesidades de memoria. El GC negocia la memoria con el sistema operativo y, como tal, se ve afectado por la memoria física disponible y todos los demás procesos en la máquina, tanto administrados como no administrados. Si bien dudo que el GC realmente sepa "cuándo es un buen momento para recolectar" sobre una base "caso por caso", es muy probable que tenga una mejor estrategia en general que ... CUALQUIER aplicación única. ;)
The Dag
2

El deseo de llamar a GC.Collect () generalmente es tratar de encubrir los errores que cometió en otro lugar.

Sería mejor si encuentra dónde se olvidó de desechar las cosas que ya no necesita.

Sam
fuente
5
eso es quizás una generalización
MickyD
1

En pocas palabras, puede crear un perfil de la aplicación y ver cómo estas colecciones adicionales afectan las cosas. Sin embargo, te sugiero que te mantengas alejado a menos que vayas a hacer un perfil. El GC está diseñado para cuidarse solo y, a medida que evoluciona el tiempo de ejecución, pueden aumentar la eficiencia. Usted no quiere un montón de código rondando que puede estropear el trabajo y no poder aprovechar estas mejoras. Existe un argumento similar para usar foreach en lugar de for, es decir, que se pueden agregar mejoras futuras bajo las cubiertas a foreach y su código no tiene que cambiar para aprovechar.

Christopher Elliott
fuente
1

El .NET Framework en sí nunca fue diseñado para ejecutarse en un entorno en tiempo real. Si realmente necesita procesamiento en tiempo real, puede usar un lenguaje en tiempo real incrustado que no esté basado en .NET o usar .NET Compact Framework que se ejecuta en un dispositivo Windows CE.

Scott Dorman
fuente
Podría estar usando .Net Micro Framework, que FUE diseñado para entornos en tiempo real.
TraumaPony
@TraumaPony: Consulte la tabla al final de esta página. Msdn.microsoft.com/en-us/embedded/bb278106.aspx : Claramente, Micro Framework no fue diseñado para entornos en tiempo real. Sin embargo, fue diseñado para entornos integrados (como WinCE) pero con menores requisitos de energía.
Scott Dorman
1

Lo peor que puede hacer es hacer que su programa se congele un poco. Entonces, si le parece bien, hágalo. Por lo general, no es necesario para aplicaciones web o de cliente pesado con mayor interacción del usuario.

He descubierto que a veces los programas con subprocesos de ejecución prolongada o programas por lotes obtendrán la excepción OutOfMemory aunque estén eliminando los objetos correctamente. Uno que recuerdo fue el procesamiento de transacciones de una base de datos de línea de negocio; la otra era una rutina de indexación en un hilo en segundo plano en una aplicación cliente pesada.

En ambos casos, el resultado fue simple: Sin GC. Recolectar, sin memoria, de manera consistente; GC.Collect, rendimiento impecable.

Lo he intentado para resolver problemas de memoria varias veces, sin éxito. Lo saqué.

En resumen, no lo coloque a menos que obtenga errores. Si lo coloca y no soluciona el problema de memoria, retírelo. Recuerde probar en el modo de lanzamiento y comparar manzanas con manzanas.

El único momento en que las cosas pueden salir mal con esto es cuando te vuelves moralista al respecto. No es una cuestión de valores; muchos programadores han muerto y se han ido directamente al cielo con muchos GC.Collects innecesarios en su código, que les sobrevive.

FastAl
fuente