20 puntos por carnoxen 2024-11-27 | 11 comentarios | Compartir por WhatsApp

Resumen

Este es un texto escrito mientras observaba la disputa entre desarrolladores de Rust y desarrolladores tradicionales de Linux. Varios desarrolladores pueden tener distintos estilos de programación, pero el proyecto Linux ya tiene el antecedente de haber excluido C++ para evitar su estilo y estructura de código (RAII).

La forma en que funciona el código mencionado por Asahi Lina es demasiado lenta al terminar ese programa, y entra en conflicto con el procesamiento por lotes, que es la manera más básica de crear software orientado al rendimiento. Por ejemplo, usar regiones de memoria para hacer trabajo por lotes permite coordinar múltiples tiempos de vida como uno solo, por lo que no se necesita RAII.

Aquí presento materiales que respaldan mi argumento. Todos estos materiales explican por qué el procesamiento por lotes es bueno:

Por lo tanto, creo que Linux no debería aceptar RAII jamás.


La razón por la que traje este texto es la siguiente. Vi varias veces a desarrolladores coreanos de Rust muy molestos al leer ese artículo, así que me dio curiosidad saber qué pensarían aquí. ¿Ustedes qué opinan?

11 comentarios

 
techiemann 2024-12-03

En mi opinión, puedo entender hasta cierto punto el elitismo de ciertos desarrolladores. Desde una perspectiva de la "ingeniería" de software, especialmente en el caso de Linux, hoy en día es difícil encontrar un "software" que, dentro del mundo del código abierto, también haya colaborado ampliamente con el mundo cerrado y contribuido al avance de la filosofía del open source. Quizá por eso mantienen una postura conservadora, que incluso puede parecer excluyente y ludita: temen que programadores no comprobados entren en masa blandiendo Rust, peguen código sin ton ni son fuera del control de los núcleos de mantenimiento existentes del proyecto, aumenten a lo loco la deuda técnica y terminen acortando el ciclo de vida de Linux.

Es curioso adoptar una actitud no tan "abierta" para que el código abierto siga siendo código abierto durante mucho tiempo.

 
nullbus 2024-12-02

Yo también suelo usar y recomendar con frecuencia RAII o formas similares de gestión de recursos. Incluso si uno no sabe qué es RAII y lo usa de forma mecánica, de todos modos sale un código "al menos seguro".

Sin embargo, si no se usa entendiéndolo bien, es muy fácil terminar produciendo en masa código ineficiente, como abrir y cerrar decenas de veces algo que bastaría con abrir una sola vez. Si el desarrollador mantiene un interés constante en el rendimiento y esa cultura existe como base en el equipo de desarrollo, creo que incluso con RAII se puede lograr un nivel de rendimiento suficientemente bueno.

 
aer0700 2024-11-30
  1. RAII: ejecutar free cada vez que cada objeto desaparece
  2. ¿Ejecución por lotes? ¿Juntar las cosas que hay que liberar y ejecutarlas en bulk?
    ¿Existe en Linux alguna función, algo como una API, que haga que 2 se ejecute más rápido que 1?
    Yo naturalmente siempre he vivido con 1, así que no termino de entenderlo bien.
 
kandk 2024-11-29

No quiero volver a esa experiencia de desarrollo de terminar todo y luego buscar fugas de memoria con valgrind.

 
kandk 2024-11-29

No lo sé con exactitud, pero decir que no se va a usar RAII me suena a que pretenden mejorar el rendimiento usando fugas de memoria intencionales (al cerrar), aunque no estoy seguro de que esa sea la dirección correcta.
De todos modos, un desarrollador que sabe gestionar bien la memoria manualmente también sabrá usar bien RAII, y un desarrollador que no puede programar sin RAII tampoco podrá gestionar la memoria manualmente, así que no parece haber una razón para no usar RAII.

 
foriequal0 2024-11-29

Tenía curiosidad por saber cuánto tiempo consume free, así que, aunque difiere bastante de una carga de trabajo real, hice una prueba con un código simple. (Usé un build release de Rust, con std::alloc::alloc y std::fs::File.)
Asigné 10,000,000 bloques de memoria de distintos tamaños, unos 2.5 GB en total, y al medir solo el tiempo de liberación, tardó 1.87 segundos. Eso da 187 ns por bloque.
En cambio, en el caso de los archivos, dejé abiertos solo unos 10,000 handles y medí únicamente el tiempo de cerrarlos; fueron unos 9 segundos. Es decir, unos 900 us por archivo.
(En esta PC con Windows las operaciones con archivos son particularmente lentas, quizá por el antivirus. En otra laptop con Windows fueron 400 ns/200 us respectivamente, y en otra PC con Linux fueron 50 ns/600 ns.)

Como alternativa a RAII, se suele mencionar mucho el procesamiento en lote o confiar en el SO al finalizar y dejar que haya fuga de recursos, pero eso parece fácil de hacer si hablamos de memoria.
Sin embargo, para recursos como archivos o sockets, nunca he visto una API de recolección en lote, y si se dejan fugas de recursos, quizá el tiempo en el código de usuario baje, pero ese tiempo reducido termina trasladándose tal cual al tiempo que el kernel tarda en finalizar el proceso, así que el beneficio de rendimiento no parece gran cosa.

RAII para memoria tampoco es algo relativamente tan lento, ni es una técnica que vuelva imposible usar arenas, ni impide hacer fugas intencionales cuando se necesita, así que no parece una razón muy convincente para evitar RAII.
Y en el caso de RAII para archivos, que es más lento, cuando no hay forma de procesarlo en lote ni de evitar ese costo, me pregunto cuánto mejor es realmente la alternativa a RAII.


Aunque se sale un poco del tema, me da la impresión de que las objeciones sobre RAII y lifetimes suelen discutirse limitándolas solo a recursos de memoria representados por malloc/free.
RAII y los lifetimes no sirven solo para la asignación de memoria, sino también para modelar de forma muy útil recursos del SO como archivos, sockets y locks, además de pools de objetos, pools de conexiones y, en general, la mayoría de los recursos donde hay adquisición y devolución, y donde se necesita control de acceso exclusivo mientras están adquiridos.

Estos recursos también comparten una estructura similar a malloc/free, así que comparten problemas de la misma forma, como fugas, use after free y double free,
y justamente por compartir esa misma estructura, creo que habría que destacar más que RAII y los lifetimes resuelven de una sola vez no solo los problemas de memoria, sino también los de este tipo de recursos.
Por ejemplo, en Rust también se previenen en tiempo de compilación el use after close y el double close para file handles:
https://play.rust-lang.org/?version=stable&mode=debug&edition=…

Los principales lenguajes con GC gestionan la memoria con GC, pero al final, para recursos como file handles y sockets, cuya gestión debe ser determinista,
terminan introduciendo además estructuras como RAII (como try-with-resources de Java, using de C# o with de Python) o estructuras parecidas (como defer de Go),
con lo que al final un mismo lenguaje termina teniendo varios modos de gestión de recursos; me parece que esto no está un poco peor que la alternativa.

 
crosh 2024-11-28
  1. Es cierto que al excluir C++ de Linux se evitó RAII, pero eso no parece suficiente como evidencia de que Linux evitó C++ "para evitar RAII". En la carta de Linus que presentó no aparece la palabra RAII.
  2. Para ser sincero, a partir del párrafo que empieza con Asahi Lina..., todos los enlaces presentados son videos de YouTube de varias decenas de minutos, así que es difícil verlos. Creo que la discusión se activaría más si diera ejemplos técnicos, basados en casos concretos, donde RAII no sea necesario.

Por ejemplo, usar una región de memoria para hacer trabajo por lotes permite coordinar varias vidas útiles como una sola, así que no se necesita RAII.

Si con eso se refiere a un arena, entonces por supuesto Rust también tiene arenas, y también es posible, al eliminar el arena mediante lifetime, prohibir el acceso a los elementos del arena después de la "liberación en bloque". Consulte https://crates.io/keywords/arena.

 
ztaka 2024-11-28

Ojalá aparecieran muchos más lenguajes incluso después de Zig o Rust. Pero hasta ahora no he visto ninguno tan adecuado como Rust. Más bien, creo que el conocimiento entre desarrolladores que surge de estas discusiones entre lenguajes es lo que realmente resulta útil. Jaja..

 
shoyuvanilla 2024-11-28

Yo también soy, a mi manera, un desarrollador que usa Rust como lenguaje principal, así que no me enojó, pero sí me dio la impresión de que estaba recurriendo a un ejemplo algo extremo (cuando dice "ese programa es demasiado lento al cerrarse", incluso en el video enlazado pone un caso que no está directamente relacionado con un proyecto en Rust: que al cerrar Visual Studio se llaman los destructores de cada componente individual y por eso tarda demasiado).

Si por rendimiento hace falta que la limpieza de varios componentes se procese de una sola vez, parece que en vez de implementar Drop para cada componente individual se podría optar por implementar Drop en el tipo que mantiene la vida útil de esos componentes, para ejecutar allí toda la limpieza de una vez. Y sería todavía mejor si se pusiera alguna garantía de seguridad para que esos componentes solo puedan crearse a través de la API de ese tipo.

Por supuesto, creo que la preocupación del autor del texto es que, si la práctica de usar RAII entra en el codebase de Linux, dentro de la complejidad de una base de código enorme se vayan acumulando con el tiempo fragmentos con problemas de rendimiento muy implícitos, y que a largo plazo termine ocurriendo algo parecido a lo de Visual Studio; me parece una preocupación totalmente válida. Aun así, como mencionaron en otros comentarios, también está la estabilidad que aporta RAII, así que diría que la elección es, en cierta medida, un trade-off.

 
cosine20 2024-11-28

Ambas partes están diciendo cosas correctas.

Por poner una analogía, en el juego en línea LoL existe la percepción de que Azir es un campeón de tier alto, abrumadoramente bueno por su capacidad de split push, control de zona en peleas en equipo y el valor de su definitiva, pero eso solo aplica en partidas profesionales de altísimo nivel; al nivel de la gente común, su fase de líneas es demasiado débil y su poder base también, así que no deja de ser un campeón de tier bajísimo.

Desde la perspectiva de personas como Asahi Lina, que están en el 10% superior en conocimientos de programación y sistemas operativos, una alternativa distinta de RAII seguramente será mejor, pero creo que en las áreas que maneja el otro 90% no hay nada tan bueno como RAII o Rust.

Sin embargo, como una de las grandes razones por las que se debe garantizar la estabilidad/seguridad de memoria es el problema de la seguridad informática... creo que ese tradeoff es inevitable.

 
joonhwan 2024-11-28

Sin RAII, parece que los desarrolladores con relativamente menos experiencia terminarían generando muchos bugs.

Al menos a nivel de aplicaciones, no del SO...