Tanto la velocidad como la funcionalidad.
La historia de la memoria virtual
Todos los sistemas operativos modernos como Windows, Linux y MacOS utilizan memoria virtual. La memoria virtual es una forma limpia, asistida por hardware, de mentir a su ordenador sobre la cantidad de memoria que hay. Su CPU tiene una Unidad de Gestión de Memoria (MMU), que asigna la memoria utilizada por cada programa a la memoria física real. Esto da dos ventajas instantáneas: cada programa comienza en la misma ubicación en la memoria, desde el punto de vista de ese programa, y todos los programas están aislados unos de otros. El programa A no tendrá acceso a la memoria del programa B.
Pero digamos que tienes un ordenador de 8GB y tanto el programa A como el programa B asignan cada uno un buffer de memoria de 4GB. Eso es demasiado, por supuesto, pero también ocurre que los diseñadores del SO saben que a veces, los programadores piden mucho más de lo que van a necesitar. Así que cada uno de esos bloques de 4GB se asignará en la memoria virtual, pero no necesariamente se asignará realmente. Cada programa (cada proceso) tiene su propia asignación de memoria, dividida en pequeñas «páginas» de memoria. La tabla de la MMU puede actualizarse para estas asignaciones, pero algunas o todas esas páginas se marcan como no asignadas realmente.
Así que, mientras los programas se ejecutan, la memoria que no está en la memoria marcará una trampa del procesador cuando un procesador intente acceder a ella. Esa trampa salta al gestor de memoria del sistema operativo. Si todavía hay memoria disponible, parte de ella se asignará a la RAM física y a la página que ha sido atrapada, y por razones de eficiencia, probablemente algunas más. Un beneficio inmediato de esto es que el programa, gracias a la gestión de la memoria, puede obtener un bloque contiguo de memoria, hasta los 4GB solicitados en este caso, aunque no exista un bloque contiguo en la memoria real y física.
¿Pero qué pasa si no queda memoria? Una opción sería, por supuesto, marcar eso como un error de falta de memoria y terminar el programa. Pero hace mucho tiempo, los diseñadores de sistemas operativos se dieron cuenta de que muchos programas cargan código que sólo se usa una vez o se usa raramente. Los usuarios pueden cargar programas que pueden permanecer inactivos, consumiendo recursos para poco valor. Así que las tablas de gestión de memoria del sistema también hacen un seguimiento de las páginas de la MMU que se han utilizado en absoluto, las que se han utilizado recientemente, etc. Y esto permite al sistema operativo descargar parte de la memoria no utilizada, para satisfacer esta necesidad de más RAM para el programa A.
Ahora bien, si las páginas de memoria que se están recuperando contienen código ejecutable, se trata de código que se cargó desde la imagen del programa en el disco. Esa página puede ser simplemente marcada como no-en-memoria, y esa RAM recuperada. Sin embargo, si la memoria contiene datos, estos tienen que ser colocados en algún lugar. Ese lugar es casi siempre un lugar en el disco. Los sistemas Windows tienen un «archivo de intercambio», mientras que los sistemas Linux suelen tener una «partición de intercambio». De cualquier manera, hay un trozo de disco en algún lugar, tanto si usas HDD como SSD, que está ahí para virtualizar tu RAM.
El golpe de rendimiento de la VM
Así que hay una pequeña sobrecarga en la gestión básica de la memoria, o eso parece. Al fin y al cabo, cada vez que tu programa hace una trampa en el gestor de memoria, es un trozo de tiempo consumido que hubiera sido una sola instrucción. Así que en cierto modo, sí, está haciendo las cosas más lentas.
Pero la verdadera ralentización va al disco en lugar de a la RAM. No importa si tienes una vieja unidad IDE paralela o el último SSD M.2 en cuatro canales PCIe, tu disco es muchas, muchas veces más lento que tu DRAM. Así que la primera ventaja de tener más memoria es evitar los fallos de página, esas trampas para el gestor de memoria que necesitan intercambiar en el disco.
La ventaja del rendimiento de la VM
Considere también que la memoria virtual no apareció mágicamente un día en un sistema operativo moderno. Los diseñadores de sistemas operativos, los programadores de aplicaciones, etc., han vivido con la memoria virtual durante más de cincuenta años. Hay enormes beneficios de rendimiento con la memoria virtual.
Uno es simplemente exprimir esa aplicación que no cabría de otra manera. Allá por los años 90, trabajaba en una empresa que hacía una aplicación de presentación multimedia. Esta aplicación se ejecutaba en MS-DOS, pero barajando muchas fotos y vídeos, podía ser un reto. MS-DOS, por supuesto, no tenía memoria virtual. Pero en aquellos días, si ejecutabas un programa de MS-DOS en el OS/2 de IBM, utilizaba el gestor de memoria de OS/2 y ¡voilá! Memoria virtual con paginación. Así que presentaciones que no se ejecutarían bajo MS-DOS se ejecutarían bajo OS/2 en la misma plataforma informática limitada de aquellos días.
Se utilizan algunas otras características, con paginación o sin ella. Como el gestor de memoria sabe qué memoria se asignó, puede recuperarla toda sin necesidad de que las aplicaciones gasten esfuerzo de codificación en recuperarla. Esto no es una excusa para la programación descuidada, pero va unido a ese factor de protección: los recursos de un programa muerto pueden ser encontrados y devueltos al sistema. Otros aspectos del diseño de programas evolucionaron para aprovechar los sistemas de memoria virtual también.
Y los propios sistemas operativos evolucionaron. Dado que un sistema gestionado por la memoria puede adaptarse a la RAM disponible, los sistemas operativos modernos no se limitan a dejar la RAM sin utilizar por ahí, sino que la asignan cuando no se utiliza para acelerar el sistema. Los búferes de memoria más grandes, los trozos de código que podrían necesitarse más tarde, etc. pueden asignarse sin temor a ahogar los programas de usuario.
Esto no es ilimitado, por supuesto. Tengo un sistema aquí con 64GB de DRAM, ejecutando un navegador, un programa CAD, y algunas utilidades, y estoy usando 21,8GB. Esto se ejecutaría fácilmente en un sistema de 16GB, funcionaría bastante bien en un sistema de 8GB. Pero las optimizaciones que hace el sistema operativo para acelerar las cosas se perderían, así que tendría un sistema más lento. Es posible que en el caso de 8GB viera suficiente paginación de memoria como para que se notara aún más la ralentización.
Más RAM, más capacidad… Al margen
Naturalmente, al hablar de memoria grande, estamos hablando de sistemas de 64 bits. La «regla general» común para la memoria es de al menos 2GB por núcleo de CPU, así que hoy en día, 8GB en un sistema de 4 núcleos, 16GB en un sistema de 6 núcleos como el mío (12GB no es una opción). Esto se basa en el antiguo límite de 32 bits de la mayoría de los sistemas operativos de 2-3 GB por proceso de usuario y en la suposición de que no se están ejecutando demasiados programas diferentes a la vez que realmente consumen tiempo de la CPU (los que están inactivos, por supuesto, pueden salir de la memoria sin mucha ralentización). Pero eso es sólo una pauta mínima.
Y algunas cosas simplemente no funcionan en trozos más pequeños de memoria, pero dado el tamaño de la RAM en los ordenadores promedio en estos días, el número de estas aplicaciones parpadea regularmente. Antes de mi última actualización de PC, en 2013, tenía un PC con 16GB de RAM, y me frenaba. Una de las cosas que hago son grandes composiciones fotográficas, y el programa principal que utilizo para esto es bastante hambriento de memoria. Estoy uniendo docenas de imágenes de 16Mpixel o 20Mpixel, y me estaba topando con un muro, quedándome sin memoria incluso con un archivo de página bastante grande.
Así que construí mi nuevo PC con 64GB DRAM, lo máximo que la placa base podía manejar, y procedí a ejecutar algunas de esas composiciones fotográficas… e inmediatamente me quedé sin memoria. Así que eso fue en mí – Traté de dos al mismo tiempo. Yendo de uno en uno, soy bastante bueno estos días.