Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

Este artículo analiza un caso para acelerar una aplicación de navegador reemplazando los cálculos de JavaScript con WebAssembly.

WebAssembly: ¿qué es?

En resumen, este es un formato de instrucción binaria para una máquina virtual basada en pila. Wasm (nombre corto) a menudo se denomina lenguaje de programación, pero no lo es. El formato de instrucción se ejecuta en el navegador junto con JavaScript.

Es importante que WebAssembly se pueda obtener compilando fuentes en lenguajes como C/C++, Rust, Go. Aquí se utilizan la tipificación estadística y el llamado modelo de memoria plana. El código, como se mencionó anteriormente, se almacena en un formato binario compacto, lo que lo hace casi tan rápido como ejecutar la aplicación usando la línea de comando. Estas capacidades han llevado al crecimiento de la popularidad de WebAssembly.

Recordamos: para todos los lectores de "Habr": un descuento de 10 rublos al inscribirse en cualquier curso de Skillbox utilizando el código promocional "Habr".

Skillbox recomienda: Curso práctico "Desarrollador móvil PRO".

Actualmente, Wasm se utiliza en muchas aplicaciones, desde juegos como Doom 3 hasta aplicaciones portadas a la web como Autocad y Figma. Wasm también se utiliza en áreas como la informática sin servidor.

Este artículo proporciona un ejemplo del uso de Wasm para acelerar un servicio web de análisis. Para mayor claridad, tomamos una aplicación funcional escrita en C, que está compilada en WebAssembly. El resultado se utilizará para reemplazar las secciones de JS de bajo rendimiento.

Transformación de aplicaciones

El ejemplo utilizará el servicio de navegador fastq.bio, que está destinado a genetistas. La herramienta le permite evaluar la calidad de la secuenciación (descifrado) del ADN.

A continuación se muestra un ejemplo de la aplicación en acción:

Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

No vale la pena entrar en detalles del proceso, ya que son bastante complejos para los no especialistas, pero en resumen, los científicos pueden utilizar la infografía anterior para comprender si el proceso de secuenciación del ADN se desarrolló sin problemas y qué problemas surgieron.

Este servicio tiene alternativas, programas de escritorio. Pero fastq.bio te permite acelerar tu trabajo visualizando los datos. En la mayoría de los demás casos, es necesario poder trabajar con la línea de comandos, pero no todos los genetistas tienen la experiencia necesaria.

Todo funciona de forma sencilla. La entrada son datos presentados en forma de archivo de texto. Este archivo es generado por herramientas de secuenciación especializadas. El archivo contiene una lista de secuencias de ADN y una puntuación de calidad para cada nucleótido. El formato del archivo es .fastq, de ahí el nombre del servicio.

Implementación en JavaScript

El primer paso del usuario cuando trabaja con fastq.bio es seleccionar el archivo apropiado. Usando el objeto Archivo, la aplicación lee una muestra aleatoria de datos de un archivo y procesa ese lote. El trabajo de JavaScript aquí es realizar operaciones de cadenas simples y calcular métricas. Uno de ellos es el número de nucleótidos A, C, G y T en diferentes fragmentos de ADN.

Después de calcular los indicadores necesarios, se visualizan utilizando Plotly.js y el servicio comienza a funcionar con una nueva muestra de datos. La fragmentación se realiza para mejorar la calidad de la UX. Si trabaja con todos los datos a la vez, el proceso se congelará durante algún tiempo, ya que los archivos con los resultados de la secuenciación ocupan cientos de gigabytes de espacio. El servicio toma datos de entre 0,5 y 1 MB de tamaño y trabaja con ellos paso a paso, generando datos gráficos.

Así es como funciona:

Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

El rectángulo rojo contiene el algoritmo de transformación de cadenas para obtener la visualización. Esta es la parte del servicio con mayor intensidad computacional. Vale la pena intentar reemplazarlo con Wasm.

Prueba de ensamblaje web

Para evaluar la posibilidad de utilizar Wasm, el equipo del proyecto comenzó a buscar soluciones listas para usar para crear métricas de control de calidad (QC - control de calidad) basadas en archivos fastq. La búsqueda se realizó entre herramientas escritas en C, C++ o Rust, de modo que fue posible portar el código a WebAssembly. Además, la herramienta no debería estar “en bruto”, sino que se necesitaba un servicio que ya hubiera sido probado por los científicos.

En consecuencia, se optó por segundo. La aplicación es bastante popular, es de código abierto y el idioma fuente es C.

Antes de realizar la conversión a Wasm, vale la pena observar el principio de compilación de seqtk para el escritorio. Según Makefile, esto es lo que necesita:

# Compile to binary
$ gcc seqtk.c 
   -o seqtk 
   -O2 
   -lm 
   -lz

En principio, puedes compilar seqtk usando Emscripten. Si no está ahí, nos las arreglamos. imagen acoplable.

$ docker pull robertaboukhalil/emsdk:1.38.26
$ docker run -dt --name wasm-seqtk robertaboukhalil/emsdk:1.38.26

Si se desea, Puedes montarlo tú mismo., pero lleva tiempo.

Dentro de un contenedor, puedes usar fácilmente emcc como alternativa a gcc:

# Compile to WebAssembly
$ emcc seqtk.c 
    -o seqtk.js 
    -O2 
    -lm 
    -s USE_ZLIB=1 
    -s FORCE_FILESYSTEM=1

Cambios mínimos:

En lugar de generar un archivo binario, Emscripten usa .wasm y .js para generar los archivos, que se usan para ejecutar el módulo WebAssemby.

El indicador USE_ZLIB se utiliza para admitir la biblioteca zlib. La biblioteca se distribuyó y se portó a WebAssembly y Emscripten la incluye en el proyecto.

El sistema de archivos virtual Emscrippten está activado. Este FS tipo POSIX, ejecutándose en la RAM dentro del navegador. Cuando se actualiza la página, se borra la memoria.

Para comprender por qué se necesita un sistema de archivos virtual, vale la pena comparar la forma en que ejecuta seqtk desde la línea de comandos con la forma en que ejecuta un módulo WebAssembly compilado.

# On the command line
$ ./seqtk fqchk data.fastq
 
# In the browser console
> Module.callMain(["fqchk", "data.fastq"])

Es necesario obtener acceso al sistema de archivos virtual para no reescribir seqtk para cadenas en lugar de entradas de archivos. En este caso, el fragmento de datos se muestra como un archivo data.fastq en el FS virtual con una llamada a main() seqtk en él.

Aquí está la nueva arquitectura:

Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

La figura muestra que en lugar de cálculos en el hilo principal del navegador, Trabajadores web. Este método le permite realizar cálculos en un hilo en segundo plano sin afectar la capacidad de respuesta del navegador. Bueno, el controlador WebWorker inicia el Worker, gestionando su interacción con el hilo principal.

El comando seqtk se ejecuta usando Worker en el archivo montado. Una vez completada la ejecución, el Trabajador produce un resultado en forma de Promesa. Cuando el hilo principal recibe un mensaje, el resultado se utiliza para actualizar los gráficos. Y así sucesivamente en varias iteraciones.

¿Qué pasa con el rendimiento de WebAssembly?

Para evaluar el cambio en el rendimiento, el equipo del proyecto utilizó el parámetro de operaciones de lectura por segundo. No se tiene en cuenta el tiempo que lleva crear gráficos interactivos ya que ambas implementaciones utilizan JavaScript.

Al utilizar la solución lista para usar, el aumento de rendimiento fue nueve veces.

Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

Este es un resultado excelente, pero resulta que también existe la oportunidad de optimizarlo. El hecho es que seqtk no utiliza una gran cantidad de resultados de análisis de control de calidad, por lo que pueden eliminarse. Si hace esto, el resultado mejora 13 veces en comparación con JS.

Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

Se logró simplemente comentando los comandos printf().

Pero eso no es todo. El hecho es que en esta etapa fastq.bio recibe los resultados del análisis llamando a diferentes funciones C. Cada una de ellas calcula su propio conjunto de características, de modo que cada fragmento del archivo se lee dos veces.

Para solucionar este problema, se decidió combinar dos funciones en una. Como resultado, la productividad aumentó 20 veces.

Cómo usamos WebAssembly para acelerar una aplicación web 20 veces

Vale la pena señalar que no siempre es posible lograr un resultado tan sobresaliente. En algunos casos, el rendimiento bajará, por lo que vale la pena evaluar cada caso.

Como conclusión, podemos decir que Wasm brinda la oportunidad de mejorar el rendimiento de la aplicación, pero debe usarse con prudencia.

Skillbox recomienda:

Fuente: habr.com

Añadir un comentario