
Cada aplicación que creabas con la aplicación de escritorio de WebCatalog ocupaba unos 320 MB de espacio en disco en macOS. No es algo inusual para una aplicación basada en Electron, pero WebCatalog está diseñado para personas que usan muchas aplicaciones web como aplicaciones de escritorio. Si instalabas diez, podían ocupar más de 3 GB, aunque la mayor parte de los datos de esas aplicaciones fueran exactamente iguales.
Hace poco cambiamos la forma en que la aplicación de escritorio de WebCatalog crea aplicaciones en macOS. La primera aplicación ahora utiliza unos 340 MB de espacio físico en disco, incluida una copia preparada del motor de aplicaciones que se conserva localmente. Después, cada aplicación adicional suele añadir solo 1–2 MB de uso real del disco. En nuestras pruebas, diez aplicaciones pasaron de ocupar más de 3 GB a unos 360 MB.
Lo conseguimos con una función que ya incluye macOS: los clones de APFS. Lo interesante no fue simplemente clonar archivos, sino lograr que la clonación funcionara sin perder la independencia de cada aplicación, manteniendo una firma de código válida y conservando el mismo funcionamiento que una aplicación creada con el proceso anterior.
Por qué cada aplicación ocupaba otros 320 MB
La aplicación de escritorio de WebCatalog convierte sitios web en aplicaciones de escritorio independientes. Cada aplicación que creas se ejecuta sobre Photon, nuestro motor de aplicaciones basado en Electron. En macOS, cada una es un paquete .app normal que contiene Electron (Chromium y Node.js), Photon y los archivos específicos de esa aplicación.
Tomemos como ejemplo Slack y Discord. Sus nombres, iconos, identificadores de paquete y configuraciones son distintos, pero el gran framework de Electron y la mayor parte de Photon son idénticos.
Hasta ahora, cada aplicación se creaba como una copia completamente independiente.
Slack.app
Electron
Photon
Archivos específicos de Slack
Discord.app
Electron
Photon
Archivos específicos de Discord
El framework de Electron y Photon podían ser idénticos byte por byte en ambas aplicaciones, pero macOS almacenaba otra copia física por cada aplicación. Por tanto, diez aplicaciones suponían aproximadamente diez copias de un paquete de aplicación de 320 MB prácticamente idéntico.
Esa arquitectura sí tenía una propiedad que queríamos conservar: cada aplicación era completamente independiente. Eliminar una no podía afectar a otra, y las aplicaciones instaladas no dependían de que la aplicación de escritorio de WebCatalog siguiera presente en el sistema.
Lo que queríamos eliminar era la duplicación innecesaria de los datos subyacentes.
APFS ya tenía el mecanismo que necesitábamos
Los Mac modernos utilizan APFS, el sistema de archivos de Apple. APFS admite la clonación, un mecanismo de copia en escritura que permite que dos archivos independientes compartan los mismos datos físicos hasta que uno de ellos cambia.
Imagina que copias un archivo de 300 MB. Con una copia normal, macOS escribe otros 300 MB en el disco, por lo que ambos archivos ocupan unos 600 MB en total.
Con un clon de APFS, el archivo nuevo sigue pareciendo un archivo completo de 300 MB y se comporta como tal, pero al principio apunta a los mismos bloques físicos que el original.
Archivo A ─────┐
├── bloques físicos compartidos
Archivo B ─────┘
Si más adelante cambia una parte del archivo B, APFS escribe bloques nuevos solo para los datos modificados. Todo lo que siga siendo idéntico puede continuar compartiendo los bloques originales.
Archivo A ───────── bloques compartidos
Archivo B ───────── bloques compartidos
└──────── bloques modificados
Desde el punto de vista de la aplicación, los archivos A y B son independientes. Desde el punto de vista del SSD, los datos idénticos solo necesitan almacenarse una vez.
Ese era casi exactamente el comportamiento que necesitábamos.
Crear aplicaciones a partir de una base común
La aplicación de escritorio de WebCatalog ahora prepara una base para cada combinación de versiones de Electron y Photon. La aplicación base de Photon contiene las partes idénticas en todas las aplicaciones, incluidos Electron, Photon, la estructura del framework y las firmas comunes.
Cuando la aplicación de escritorio crea otra aplicación con las mismas versiones, ya no extrae y construye otra copia completa desde cero. En su lugar, crea un clon de APFS de la aplicación base de Photon y personaliza únicamente las partes que deben ser diferentes.
Estas incluyen el nombre y el icono de la aplicación, el identificador de paquete, la configuración, los nombres de los ejecutables, el identificador de compilación y otros metadatos específicos de la aplicación.
Como la mayor parte del paquete permanece intacta, APFS sigue compartiendo los bloques físicos que contienen Electron y Photon. Solo la cantidad relativamente pequeña de datos específicos de la aplicación ocupa espacio nuevo.
¿Por qué no compartir simplemente Electron?
Una opción más evidente sería instalar Electron una sola vez y hacer que todas las aplicaciones apuntaran a esa instalación.
Lo consideramos, pero cambiaría de manera fundamental el modelo de fiabilidad. Si desapareciera la instalación compartida de Electron, todas las aplicaciones que dependieran de ella podrían dejar de funcionar. Un limpiador de caché podría eliminarla, desinstalar la aplicación de escritorio de WebCatalog podría borrarla, y trasladar o restaurar una aplicación individual sería más complicado.
También exigiría llevar un registro de qué aplicaciones instaladas dependen de cada versión del entorno de ejecución para poder eliminar de forma segura las versiones antiguas.
La firma de código de macOS plantea otro problema. La verificación estricta de firmas rechaza los enlaces simbólicos que apuntan fuera del paquete de la aplicación.
Los clones de APFS nos ofrecen la ventaja de compartir datos sin introducir esa dependencia. Las aplicaciones instaladas pueden compartir bloques físicos del disco y, al mismo tiempo, seguir siendo paquetes de aplicación completos e independientes.
Eliminar la aplicación base de Photon no inutiliza las aplicaciones creadas a partir de ella. Eliminar una aplicación instalada no afecta a otra. El sistema de archivos se encarga de compartir los datos, mientras que la arquitectura de las aplicaciones sigue siendo independiente.
La firma de código estuvo a punto de anular el ahorro
Clonar la aplicación era solo una parte del problema. Las aplicaciones de macOS también necesitan una firma de código.
Nuestro proceso anterior volvía a firmar exhaustivamente cada paquete de aplicación después de personalizarlo. Con una copia normal, eso no supone un problema. Sin embargo, con el almacenamiento de copia en escritura, modificar un binario grande puede hacer que APFS asigne nuevos bloques físicos.
Durante el desarrollo, medimos que volver a firmar el framework de Electron añadía aproximadamente 194 MB de almacenamiento físico por aplicación. Habíamos evitado copiar Electron al crear la aplicación, solo para volver a duplicar gran parte de él durante la firma.
Por eso también tuvimos que cambiar el proceso de firma.
Ahora el gran framework común se firma como parte de la aplicación base de Photon. Cuando la aplicación de escritorio clona esa base, evitamos modificar esos binarios grandes y compartidos y solo volvemos a firmar las partes más pequeñas que realmente deben ser diferentes entre aplicaciones.
Una vez terminada la aplicación, ejecutamos una verificación estricta de firmas sobre el paquete final para asegurarnos de que todo siga siendo válido.
Así conservamos tanto las garantías de la firma de código de macOS como el ahorro de espacio que ofrece APFS.
Cuando pedirle a Node.js que clonara no produjo un clon
Hubo otro problema inesperado: realizar la propia clonación.
Node.js ofrece indicadores de copia destinados a solicitar el comportamiento de copia en escritura, entre ellos COPYFILE_FICLONE y COPYFILE_FICLONE_FORCE. En teoría, parecían exactamente las API que necesitábamos.
En nuestras pruebas con Node.js 24, copiamos la misma aplicación de Electron de 288 MB mediante varios métodos y medimos cuánto espacio físico adicional en disco consumía cada operación:
fs.cpSync +288 MB
fs.cpSync + COPYFILE_FICLONE +288 MB
fs.cpSync + COPYFILE_FICLONE_FORCE +288 MB
/bin/cp -c -R ~0 MB
Ambos modos de clonación de Node.js produjeron una copia física completa en nuestra prueba, e incluso la variante FORCE no notificó ningún error cuando no se produjo la clonación esperada.
La operación nativa cp -c de macOS se comportó como esperábamos, así que la aplicación de escritorio de WebCatalog utiliza ese mecanismo directamente.
También fue un buen recordatorio de que las optimizaciones del sistema de archivos deben comprobarse midiendo el propio sistema de archivos. Llamar a una API que solicita copia en escritura no significa necesariamente que los archivos resultantes compartan almacenamiento físico.
Hacer que la optimización pueda fallar sin causar problemas
Ahorrar espacio en disco es una optimización. Instalar correctamente una aplicación es imprescindible.
Diseñamos el nuevo proceso para que un fallo de clonación no impida instalar la aplicación. Si falla la preparación de la aplicación base de Photon, si la base almacenada en caché está dañada, si falla la clonación o si no se supera la verificación de firmas, la aplicación de escritorio vuelve al proceso de creación anterior, con extracción y firma completas.
Por tanto, en el peor de los casos, se usa el mismo espacio en disco que antes; la instalación no falla.
También tuvimos que tener en cuenta la concurrencia. Primero se prepara una aplicación base de Photon en un directorio temporal y solo se traslada a su ubicación definitiva cuando está completa. Así, dos aplicaciones que se estén creando al mismo tiempo no pueden encontrarse por accidente con una base a medio construir.
Las bases antiguas también pueden eliminarse de forma segura. Un clon de APFS instalado no depende de que la base original siga existiendo. Si se elimina la base, el clon conserva los bloques físicos que todavía utiliza.
Esto funciona en APFS, el sistema de archivos predeterminado de todos los Mac modernos. Si tus aplicaciones están en un disco que no permite la clonación, como una unidad externa HFS+ o exFAT, la aplicación de escritorio de WebCatalog recurre a una copia normal. Las aplicaciones funcionan como antes, pero no ahorran espacio. Por ahora, Windows y Linux no cambian.
El tamaño lógico y el tamaño físico no son lo mismo
Un efecto secundario que puede resultar un poco confuso es que Finder quizá siga indicando que cada aplicación ocupa unos 320 MB.
Esa cifra representa el tamaño lógico de la aplicación. La aplicación realmente contiene unos 320 MB de archivos y, si esos archivos se copiaran a otro lugar sin clonación, habría que escribir aproximadamente esa cantidad de datos.
Lo que cambió es el tamaño físico, es decir, cuántos bloques únicos ocupan realmente esos archivos en el disco.
Si dos aplicaciones contienen el mismo framework de 300 MB y APFS les permite compartir los mismos bloques subyacentes, cada aplicación puede contener lógicamente 300 MB, mientras que la segunda apenas añade datos físicos nuevos.
La vista Obtener información de Finder y herramientas como du no muestran necesariamente que esos datos se compartan. El ahorro se aprecia sobre todo en la cantidad de espacio libre que queda realmente en el disco.
Lo comprobamos con siete aplicaciones reales: Discord, Facebook, Instagram, Messenger, TikTok y dos aplicaciones personalizadas. Creadas de esta manera, ahorraron alrededor de 1,9 GB de espacio en disco frente al proceso de creación anterior.
También examinamos las posiciones físicas subyacentes en el disco y confirmamos que las aplicaciones compartían sus datos comunes de Electron y Photon a nivel de bloques. Una aplicación creada con el proceso anterior no compartía ninguno de esos bloques, lo que nos proporcionó una comparación útil.
El resultado
Para quien crea una sola aplicación con la aplicación de escritorio de WebCatalog, la diferencia es pequeña. De hecho, la primera aplicación ocupa un poco más de espacio en disco que antes, porque la aplicación de escritorio también conserva la aplicación base de Photon que se utiliza para crear los clones posteriores.
A partir de ahí, el beneficio crece rápidamente.
Antes
1 aplicación ~320 MB
10 aplicaciones >3 GB
Con la clonación de APFS:
Después
1 aplicación ~340 MB
10 aplicaciones ~360 MB
Una vez creada la base inicial, cada aplicación adicional suele añadir solo 1–2 MB de uso físico del disco.
Lo importante es que lo conseguimos sin introducir una dependencia de un entorno de ejecución compartido. Cada aplicación sigue siendo una aplicación de macOS normal y autónoma, mientras que APFS almacena los datos idénticos de Electron y Photon una sola vez. Con unas diez aplicaciones instaladas, esto puede reducir el uso real del disco a menos de una octava parte.
Esta función está disponible en la versión más reciente de la aplicación de escritorio de WebCatalog para macOS. No tienes que activar nada: las aplicaciones nuevas la utilizan automáticamente, y las que ya tienes ocuparán menos espacio la próxima vez que se actualicen.