Un solo hilo en NativeScript

Apenas di platica introductoria de NativeScript y me preguntaron acerca del modelo de hilos o “Threading” en NativeScript, la verdad no estaba muy familiarizado con el concepto, pero infería que era un solo hilo principal y a partir de ahi se crean con web workers, por que JavaScript no maneja multiples hilos pero los puedes simular, así lo hacen otras tecnologías como Appcelerator y React.

Investigando con los amigos de Telerik, me refirieron a un artículo publicado por Georgi Atanasov al respecto, que deja claro los beneficios del modelo de un solo hilo de NativeScript.

¿por que NativeScript corre en el hilo principal de UI en lugar de utilizar un hilo separado ? ¿ esto no afecta el performance ?

Son buenas preguntas.

Principios básicos

NativeScript se baso en la experiencia de la gente de Telerik creando herramientas de productividad para desarrolladores para crear un framework para construir aplicaciones móviles de plataforma cruzada que cualquier desarrollador puede rápida y fácilmente usar. Desde el inicio, NativeScript se enfocó en entregar una solución que:

Pusiera a disposición todas las APIs nativas a JavaScript (sin la necesidad de plugins nativos).

Entregará un performance nativo.

Optimizará la experiencia de desarrollo para desarrolladores web (especialmente desarrolladores TypeScript/Angular).

Estos principios guiaron las decisiones de la arquitectura que hicieron que NativeScript evolucionará.

¿pero por que NativeScript corre en el hilo de la UI ?

La respuesta es simple . Ejecutando JavaScript en el hilo de la UI permite a NativeScript entregar una de sus principios mas importantes: proveer acceso de gran rendimiento a 100% de las APis Nativas a través de JS. Punto. No trade-offs. Sin limites.

Poniéndolo de otra forma, si un API existe en iOS o Android (o incluso una librería de iOS o Android), tu puedes llamarla via JavaScript en Nativescript. No hay nada entre ti y la capacidad de hacer — en JavaScript cualquier cosa que veas en una app nativa creada con ObjC/Swift/Java.

Esta es una capacidad poderosa, y única entre varias alternativas como React Native y Fuse que requieren plugins en código nativo y nuevas capas de abstracción para interactuar con las APIs nativas.

Para poder hacer esto, es esencial que las interacciones entre la UI nativa y y las llamadas de JavaScript a otras APIs nativas sean rápidas. En su búsqueda, encontraron que la forma más eficiente de entregar las apps más rápidas, y al mismo tiempo habilitar el acceso al 100% a las APIS, es poniendo la aplicación de JavaScript en el mismo hilo que el código UI. Esto minimiza los problemas rendimiento (*marshalling performance problems) y tiene la ventaja de crear un modelo programación que emula muy cercanamente las arquitecturas nativas sin agregar nuevas capas de abstracción.

Otros bancos de trabajo de runtimes — synthetic runtime benchmarks demuestran que cuando se comparó con React Native, NativeScript, corriendo en el hilo principal de UI, es mas rápido en order de magnitud a las llamadas a las APIs Nativas, un comportamiento muy común en las aplicaciones móviles JavaScript. (Nota: la prueba de abajo fue realizada en iOS8+).

Conclusión

En NativeScript corremos JavaScript en el hilo de la UI para que así la UI nativa y la aplicación JavaScript — que realiza frecuentes llamadas a las APIs de las plataformas nativas — pueda comunicarse tan rápido como sea posible con el menor costo posible de marshalling. En los pruebas de rendimiento esto es rápido. Pero es más importante que la arquitectura final habilita el acceso al 100% a las APIs nativas via JavaScript.

¿No ejecutar JavaScript en el hilo de la UI causa una caída en los frames (frames to drop) ?

Si y no.

Primero, para los que no estén familiarizados, “dropped frames” son el resultados de que el hilo de la UI esta muy ocupado como para entregar suavemente, 60 fps, refreshes o actualizaciones.

Cuando una aplicación comienza a perder cuadros, la UI tartamudea e presenta lo que muchos desarrolladores ahora llaman “jank” (isolated long pauses) . Este es un problema común en las apps híbridas.

Un ejemplo de que las apps construidas con NativeScript pueden ser rápidas, fluidas y responsivas es el demo del marketplace.

Para que los que aman CSS — las animaciones en esta imagen son enteramente hechas via CSS.

Esta app esta disponible en las tiendas de Apple y en Google Play , la pueden descargar, experimentar y corroborar por ustedes mismos.

Para la mayoría de las operaciones, especialmente en “aplicaciones de negocio” comunes un dispositivo no tiene problema manejando el JAvaScript de NativeScript en el hilo de la UI mientras entrega 60 fps. Sin embargo, puede que experimentes temas de performance cuando corras una operación de uso intensivo de CPU en el hilo de la UI.

No coincidentemente, este es el exacto mismo problema que encontrarías creando aplicaciones nativas para iOs y Android usando Obj-C, Swift o Java. Por defecto, el código nativo corre en el mismo hilo que la UI nativa, así que operaciones de uso intensivo de CPU en código nativo también pueden degradar el performance de la app y acusar perdida de frames.

NativeScript, como se diseñó, se comporta igual a las apps nativas. Entonces, como en las apps nativas, la correcta solución es selectivamente descargar el código CPU intensivo a un hilo en background o segundo plano para que las animaciones y otro código relacionado a la UI continue corriendo suavemente. Correcto en las aplicaciones nativas. Correcto en NativeScript.

OK, OK, ¿ y como paso el trabajo a otros hilos en NativeScript?

Directo al punto: NativeScript no tiene un mecanismo oficial cross-platform para hacer trabajo JavaScript arbitrario en otros hilos….aún.

;-)

Alex

*marshalling en ciencias de la computación es el proceso de transformar la representación en memoria de un objeto a un formato de datos adecuado para almacenar o transmitir y este es típicamente usado cuando se deben de mover datos entre diferentes partes de un programa o de un programa a otro. Marshalling es similar a serialización y es usado para comunicar objetos remotos con un objeto en este caso un objeto serializable.

Cheerleader in chief for KMMX, RPA Enthusiast, DevOps, Technical Writer & International Speaker, Dad & 2 cats.

Cheerleader in chief for KMMX, RPA Enthusiast, DevOps, Technical Writer & International Speaker, Dad & 2 cats.