¿Por qué los desarrolladores de software dependen tanto de la recolección automática de basura?

El beneficio del código que “se limpia después de sí mismo” es en realidad relativamente menor. Administrar la memoria de manera autónoma siempre ha sido relativamente simple en C.

Donde el recolector de basura es invaluable es en el manejo del flujo de objetos entre los componentes que se construyeron de forma independiente, a menudo incluso sin la previsión de que esos componentes eventualmente se ensamblarían juntos.

En otras palabras, “el código que mágicamente sabe que no debe limpiarse después de sí mismo cuando otro código todavía está usando su memoria, y el código que mágicamente sabe limpiar después de otro código cuando nadie más todavía está usando la memoria de ese código”.

Eso es la recolección de basura, y es increíblemente útil, porque no hay soluciones decentes para lograr lo que acabo de describir fuera de la recolección de basura. El recuento de referencias a menudo no puede hacerlo. RAII no lo hace. Es literalmente imposible hacerlo a mano; en su lugar, se deben crear contratos complejos, como “manejadores”, entre los componentes para lograr esto para cada pieza de memoria o recurso que surge a través de una API.

Si alguna vez ha trabajado con sistemas grandes en idiomas sin recolección automática de basura, no tendría dudas sobre el valor de la recolección de basura. Si no ha trabajado realmente en ningún sistema grande (por ejemplo, si es un estudiante que trabaja en proyectos individuales, o trabaja en componentes pequeños, etc.), entonces el valor de un recolector de basura podría no ser obvio, porque la cuestión de “¿Quién es responsable de liberar la memoria y cuándo saben que está bien hacerlo?” Ni siquiera tendría sentido.

Encuentro difícil responder una pregunta como esta, porque es completamente obvio para mí cuál es la respuesta, y me gustaría escribir una respuesta de tal manera que se vuelva completamente obvio lo que quiero decir, pero eso es difícil lograr porque hay un conjunto de experiencias (por ejemplo, con sistemas grandes y con lenguajes que no se recolectan basura) que son imposibles de agrupar en algo menos que un libro.

Un recolector de basura es una compensación de ingeniería mejor que razonable para muchos sistemas. Algunos sistemas, como los que no pueden tolerar ninguna pausa, deberían hacer que el tradicional (antes del recolector de basura) se comprometa con una mayor complejidad y un acoplamiento más estrecho entre los componentes con respecto a la gestión de la memoria.

Por último, siempre es importante apreciar que la ingeniería se trata de compensaciones. La recolección de basura representa un conjunto de compensaciones. Uno debe evaluar esas compensaciones conscientemente, pero evitar estar predispuesto a un enfoque particular. En mi experiencia, el costo de tiempo de ejecución real (rendimiento, recursos de CPU y RAM, etc.) de la recolección de basura es a menudo minúsculo en comparación con el costo del tiempo de desarrollo (dólares, errores, complejidad, inflexibilidad, etc.) de la administración manual de memoria, pero siempre habrá algún conjunto de casos en los que el enfoque de administración de memoria manual es la mejor decisión de ingeniería. A medida que esa categoría se reduce en relación con la cantidad de software creado, es natural que cada vez menos desarrolladores sobresalgan en las habilidades de gestión de memoria manual.

En aras de la divulgación completa, trabajo en Oracle. Las opiniones y opiniones expresadas en esta publicación son mías y no reflejan necesariamente las opiniones u opiniones de mi empleador.

No, no es un “arte perdido”. Algunas personas lo saben. Pero cada vez menos personas tienen que saberlo, y cada vez más dependen del análisis estático para detectar sus errores inevitables.

Todos cometen errores. La administración automática de memoria (que incluye esquemas de conteo de referencias, así como la recolección de basura tradicional) hace que sea más fácil cometer menos errores y hace posibles algunas cosas que son prohibitivamente difíciles con la administración manual de memoria (especialmente relacionada con la concurrencia).

Le pregunto qué beneficio tangible le brinda la administración manual de memoria en la mayoría de las aplicaciones de línea de negocios (lo que diría es que los lenguajes administrados han encontrado un punto óptimo … aunque no es que no se usen en otros lugares).

La memoria administrada nos ha liberado para pensar sobre el problema en cuestión en lugar de rastrear qué objetos asigné y cuándo / dónde tengo que liberarlos.

También agregaría que solo porque uso un lenguaje administrado (C #, Java, incluso Objective-C) no significa que no necesito entender la plataforma en la que estoy trabajando. Todavía es posible “perder” memoria en todas estas plataformas y es necesario un conocimiento sólido de cómo funciona la plataforma para crear un código que funcione bien.

Por las mismas razones, dependen de las convenciones de llamadas ABI estándar y la asignación automática de registros. Estos son detalles de implementación de bajo nivel que de otro modo impedirían el desarrollo de software. Por lo tanto, creamos soluciones automáticas adecuadas para la mayor cantidad posible y pasamos a resolver los problemas reales.

Los desarrolladores de iOS escriben código que se limpia a medida que avanza.
Cocoa / Objective-C utiliza el recuento de referencias en lugar de la recolección de basura.
Esta es una mejor solución, especialmente en dispositivos móviles.

La desventaja del conteo de referencias es que puede ser más difícil para el programador. Es fácil estropear retener y liberar llamadas. Pero con el conteo automático de referencias, el compilador hace el trabajo duro.

La otra cara de ser un programador 10X ninja rockstar es reconocer que el 99% de los programadores no son tan buenos como usted, pero a menudo trabajarán en la misma base de código.

El lenguaje tiene que apoyarlos y sus imperfecciones.

Además, ¿por qué querrías cuidar la memoria tú mismo? ¿Qué valor agrega? ¿Por qué la JVM (o lo que sea) no sería mejor que un programador que pasa una pequeña fracción de su tiempo pensando en la gestión de la memoria?