Se había filtrado y era uno de los rumores de más peso: Apple presentaría una nueva transición de hardware en sus Mac. La tercera. La primera fue en el año 1994 de los procesadores de serie 68000 de Motorola hacia IBM PowerPC. Solo 11 años después, Apple anunciaba una nueva transición: de PowerPC a Intel. Y este año 2020, 15 años después, ha marcado el último paso de Apple con la transición de los Mac a lo que ha dado por llamarse comercialmente Apple Silicon.
Para entenderlo mejor, una transición es cuando una compañía decide cambiar sus procesadores, no solo por otra marca: cambia por otros con otro conjunto de instrucciones, diferente e incompatible. Y esto, obviamente, requiere una transición y transformación de todo el software que ya funcionaba con el antiguo conjunto de instrucciones hacia el nuevo.
Contexto histórico: cómo fueron las anteriores transiciones para entender la actual
En 1994 la propia Motorola fue quien dejó de trabajar con su arquitectura 680x0 hacia los chips PowerPC creados por la alianza AIM de la que formaban parte Motorola, IBM y Apple. Esto llevó a trabajar con la arquitectura RISC PowerPC. Otro conjunto de instrucciones distintos que se solventó a través de emulación de los procesadores antiguos en los nuevos. La siguiente, de RISC PowerPC a Intel x86 fue más compleja.
La transición de PowerPC a Intel supuso un enorme reto tecnológico. Las instrucciones de bajo nivel y el funcionamiento de cada arquitectura eran totalmente diferentes, incluso en cómo se representaban los bytes de datos.
En PowerPC, cuando representamos una secuencia de bytes, estos se guardan en memoria de izquierda a derecha: 0A0B0C se guardaría como 0A en la primera posición, 0B en la segunda y 0C en la tercera. Lo que se conoce como big-endian. Pero Intel lo hace al revés en función de la lectura inversa de los bytes y guarda 0C en la primera posición, 0B en la segunda y 0A en la última. El método little-endian. Esto suponía que cualquier dato que proporcionaba un programa PowerPC que se ejecutara en Intel debía invertir el orden de los bytes en memoria en tiempo real y eso acarreaba un problema de rendimiento.
Para poder ejecutar todos los programas PowerPC preexistente en Intel, Apple creó un software pionero en su época llamado Rosetta. El propósito del mismo no era emular o virtualizar el software PowerPC para que funcionara en Intel (que hubiera reducido drásticamente el rendimiento en los nuevos equipos). Rosetta traducía el código a bajo nivel que ejecutaba un PowerPC a las instrucciones equivalentes en Intel de forma automática y transparente para el usuario. Y cambiaba el orden de los bytes al almacenar en memoria de big-endian a little-endian.
Rosetta, es muy importante entender esto, es un traductor. Al igual que la piedra de la que toma su nombre que contenía el mismo texto en jeroglíficos egipcios, escritura demótica y griego antiguo, y permitió a los estudiosos comprender y traducir los jeroglíficos del antiguo Egipto y entender su significado.
Rosetta traducía las instrucciones de bajo nivel de PowerPC G3, G4 y AltiVec (operaciones de coma flotante SIMD) a Intel, en contra de la emulación que fue utilizada en la anterior transición de Motorola a PowerPC. No obstante, no soportaba apps de macOS 9 o anteriores, tampoco apps que usaran las instrucciones del G5 ni las extensiones de kernel.
La traducción se hacía al ejecutar la app, por lo que tenía un coste de rendimiento para el equipo que la diferencia de potencia de un procesador Intel a PowerPC en aquella época, era capaz de asumir casi por completo. De esta forma, las apps que podían ser traducidas en tiempo real en cada ejecución con Rosetta, tenían un rendimiento entre un 70 a un 90% de la original, dependiendo de la app o lo compleja que fuera.
Lo importante que hemos de aprender de esta parte de la historia, es que Rosetta era un servicio del sistema que funcionaba siempre que se ejecutaba una app PowerPC y traducía en tiempo real. Y además, no tenía soporte para todo el software ya que las apps más complejas y que trabajaban a menor nivel en el sistema, podían presentar problemas y requerían de una conversión a binario más compleja. Y tampoco soportaban la traducción de extensiones del kernel.
Apps en Apple Silicon, las apps que podrán ejecutarse y cómo lo harán
Ya hablé sobre cómo podría ser esta transición antes de la WWDC, pero ahora ya no hay especulaciones y vamos de lleno a la actual transición. Además, con todo lo visto, podemos entender mejor las diferencias entre aquella y esta y cómo Apple ha aprendido lecciones muy importantes y aplicado mejoras sustanciales en los procesos, además de mejor compatibilidad y facilidad para los desarrolladores.
Lo primero que tenemos que entender es que Big Sur se ejecuta de forma completamente nativa sobre Apple Silicon o sobre Intel. Es decir, Apple cuenta con dos versiones compiladas de todo el sistema operativo y cada una de sus dependencias de forma nativa y sin traducción o adaptación alguna.
A todo esto se le suma la consecución de un hito dentro de Apple muy reseñable: todas las librerías que dan servicio a iOS, iPadOS, tvOS, watchOS y macOS, ahora son las mismas en Apple Silicon. No hay versiones para cada sistema, son exactamente las mismas.
La diferencia es que su comportamiento en cada sistema puede variar, pero las instrucciones y cómo se llaman a estas, al ser las mismas, permiten que una app hecha para un sistema sea fácilmente ejecutable en otro. Empezando por la librería gráfica Metal, pasando por la API de apps SwiftUI, CoreData (base de datos), CoreLocation (localización), CoreML (aprendizaje automático) y cientos de librerías más que son iguales en su especificación y que crean el comportamiento específico para cada sistema.
Por ejemplo: si yo creo un botón para un app, la instrucción, parámetros y demás serán los mismos, pero ejecutado en Mac crearán el botón en aspecto del sistema de escritorio, si es en iOS como el texto azul destacado, en tvOS como elemento con su aspecto o en watchOS con el suyo característico. La misma instrucción, distintos comportamientos adaptados a cada sistema (cuando es aplicable que pueda existir ese cambio).
Esto supone que cualquier desarrollo nativo contra las librerías del sistema, en su gran mayoría, será “portado” a Apple Silicon con abrir el proyecto en un equipo con este tipo de chips con Xcode 12 y generar el binario universal correspondiente. De hecho, Apple ya ha portado todas sus apps de forma nativa a este nuevo sistema, no solo las que lleva el sistema como Notas, Photos, Mail, etc… también la suite iWork (Pages, Keynote y Numbers) y sus tres apps profesionales por excelencia: Final Cut Pro X, Logic Pro X y Xcode. Todo el software, componentes, librerías y demás de la propia Apple ya funciona nativamente en Apple Silicon sin traducción alguna.
Pero, ¿y el resto de apps, qué pasa con ellas? ¿Funcionarán las apps que ya usamos en los Mac basados en Intel, en los nuevos Mac basados en Apple Silicon? La respuesta es sí, pero con matices.
Dependencias: la clave para una mejor transición de las apps
Nuevo concepto que ya hemos mencionado: la dependencia. Este concepto es vital para entender cómo funcionarán las apps en Apple Silicon e incluso para las apps de iPhone y iPad que podrán ejecutarse en los nuevos Macs sin transformación alguna. Una dependencia es una librería que no hemos creado nosotros, que nos ofrece una funcionalidad concreta y que usamos con el fin de no tener que realizar todo el trabajo desde 0 en casos que no tiene sentido o que tal vez nos faciliten el trabajo de desarrollo.
Por ejemplo, si yo quiero integrarme con Facebook, lo puedo hacer creando mi propia integración o puedo usar la librería de la compañía que ya me da todas las funciones para hacerlo. Si quiero hacer operaciones matemáticas complejas, puedo crear yo una librería o puedo buscar una que me ofrezca las funciones que busco. En otras ocasiones, buscamos una dependencia que nos ayude a manejar de una forma más simple cómo una funciona API de la propia Apple (un wrapper) o buscar formas alternativas de hacer algo que aunque Apple ofrece, prefiero hacerlo con la solución de otra compañía.
Por ejemplo, si quiero cifrar criptográficamente mis datos, puedo usar la API (librería) nativa de Apple, CryptoKit o CommonCrypto, pero también puedo usar CryptoSwift que es creada por un tercero. O si quiero usar bases de datos, puedo elegir la base de datos nativa de Apple, Core Data, o usar Realm (ahora propiedad de MongoDB) que me da una solución muy eficiente y práctica. Si mi app usa una librería de Apple, esa dependencia de mi app, es nativa y todas estas están ya traducidas y funcionando nativamente en Apple Silicon. Pero, ¿si uso Realm?
Pues pueden pasar dos cosas: si nuestra dependencia está compartida como código fuente (es código abierto), en la mayoría de los casos se compilará correctamente ya que la compatibilidad con Swift, Objective-C, C, C++ y demás lenguajes no cambia en Xcode. Por lo tanto, podremos compilar nuestra app en Xcode 12 como binario universal y funcionará sin problema.
Pero una dependencia también puede ser binaria: estar previamente compilada para que no podamos ver el código por motivos de propiedad intelectual u otros. En dicho caso, tenemos (o no) un problema. Porque dicha versión compilada de la librería, deberá incluir en el binario el ejecutable para arquitectura x86_64 (Intel) y arm64 (Apple Silicon). Si es así, no hay problema. Pero si el binario es solo x86_64, la cosa cambia. Tendremos que pedirle al desarrollador que nos proporcione una versión compilada para arm64.
¿Qué pasa si no existe? Que no podremos crear la versión universal de nuestra app con la codificación nativa en Apple Silicon, ya que toda la app debe soportar la arquitectura por completo. Nuestra única solución es crear la versión traducida con Rosetta 2.
Y aquí es donde viene la nueva e importante diferencia de Rosetta 2 con Rosetta. Mientras Rosetta en la transición de PowerPC a Intel era un proceso que traducía en tiempo real mientras la app se ejecutaba, Rosetta 2 traduce en tiempo de compilación o instalación de la app. Por lo tanto, una vez traducidas las instrucciones, la nueva app funcionará “como si fuera nativa”.
Es obvio que no tendrá el mismo rendimiento pues la optimización del código a bajo nivel no es el mismo si se genera nativo a si es una traducción, pero lo importante es que el proceso de Rosetta 2 se hace cuando compilamos esa app. Tras esto, la app se ejecutará como si fuera nativa de Apple Silicon. Rosetta 2 es capaz de traducir en compilación, instalación o primera ejecución (según el caso) las apps de macOS, las apps Catalyst portadas de iPadOS, juegos (que usen Metal como librería gráfica), navegadores, compiladores JIT (Just-In-Time) como los que usan lenguajes de script como Javascript, programación gráfica de Metal a bajo nivel contra la GPU y código de aprendizaje automático con Core ML usando el motor neuronal del procesador.
Como hemos dicho, según el momento, Rosetta 2 traduce en diferentes momentos. Puede que un desarrollador haya subido su app adaptada pero al no tener todas las dependencias en ARM la ha subido como app traducida con Rosetta 2. En ese caso, ya está convertida y se arrancará o instalará al momento. Pero si bajamos una app del Mac App Store que no ha sido portada por el desarrollador y está solo en Intel, al instalar la app se hará la traducción pertinente a Apple Silicon. Si la app la bajamos de una web y tampoco está adaptada, la primera que la ejecutemos se traducirá y tardará algo más de lo normal en arrancar.
No obstante, Rosetta 2 no será capaz de traducir y ejecutar apps que usen instrucciones de bajo nivel del conjunto AVX, AVX2 o AVX512 de Intel. En esos casos, tendremos que preguntar por el sistema donde se ejecuta para no usarlas cuando estemos en Apple Silicon. Estas instrucciones sirven para decirle a la CPU cómo ha de gestionar los datos que le llegan en función del tipo de dato y cómo están supeditadas a la forma en que funcionan los chips (no a sus procesos) y no tienen equivalencia en Apple Silicon. Tampoco funcionará máquinas virtuales que funcionen sobre Intel (pues el conjunto de instrucciones de virtualización es otro no traducible), ni extensiones del Kernel que son un elemento muy específico y que obligará a los desarrolladores que lo usen a adaptar su código (una restricción que ya tenía Rosetta).
Un último y muy importante apunte de Rosetta 2: el traductor es actualizable por el sistema. Por lo que Apple puede optimizar y mejorar el proceso de traducción en sucesivas versiones y cuando volvamos a ejecutar una app traducida se "retraducirá" mejorando el código para hacerlo más óptimo y eficiente sin hacer nada más. Además las apps conservan su integridad de firma digital de la misma para garantizar que no haya problemas de seguridad tras su traducción.
Una transición increíble
Esto es mi opinión personal y nada más, basado en mis años de experiencia como desarrollador y mi conocimiento de los sistemas. Y creo que Apple ha hecho un trabajo increíble que facilita muchísimo a los desarrolladores su trabajo, siendo en algunos casos un trabajo de recompilación. Es importante notar que toda la traducción a Rosetta 2 y pruebas de las apps en la nueva arquitectura, solo podrán hacerse con un Apple Developer Transition Kit (el Mac mini con A12Z).
Yo estoy muy emocionado y no puedo esperar a probar los nuevos equipos y comprobar si realmente, cómo nos dice Apple, son tan buenos como los pintan. Pronto lo sabremos.
Ver todos los comentarios en https://www.applesfera.com
VER 24 Comentarios