14 puntos por GN⁺ 2024-11-08 | 3 comentarios | Compartir por WhatsApp
  • recall es un servicio que ofrece bots para reuniones a cientos de empresas y opera una infraestructura a gran escala en AWS
  • Para ofrecer un servicio eficiente en costos, buscaban aprovechar al máximo el rendimiento del hardware
  • Durante los últimos años, como la disponibilidad de GPUs de los proveedores cloud ha sido inestable, procesaban el video en CPU en lugar de GPU
  • Al perfilar los bots que usan Chromium headless, descubrieron que la mayor parte del tiempo de CPU no se iba en el procesamiento de video (codificación/decodificación), sino en las funciones de copia de memoria __memmove_avx_unaligned_erms y __memcpy_avx_unaligned_erms
    • memmove y memcpy son funciones de la biblioteca estándar de C (glibc) para copiar bloques de memoria
    • memmove maneja algunos casos especiales relacionados con la copia de memoria en rangos superpuestos, pero ambas pueden clasificarse como funciones de “copia de memoria”
    • El sufijo avx_unaligned_erms indica que están optimizadas para sistemas con soporte de Advanced Vector Extensions (AVX) y también para accesos a memoria no alineados
    • erms significa Enhanced REP MOVSB/STOSB, una optimización para mover memoria rápidamente en procesadores Intel modernos. Puede entenderse como “una implementación más rápida para ciertos procesadores”
  • Según el perfilado, quien más llamaba a estas funciones era el cliente WebSocket en Python que recibía los datos
    • Después venía la implementación de WebSocket de Chromium, que enviaba los datos

Problemas de WebSocket

  • Usaban un servidor WebSocket local para enviar datos de video sin procesar desde el entorno JS de Chromium hacia el codificador
  • Un stream de video raw de 1080p a 30fps requiere un ancho de banda alto, de más de 93 MB por segundo
  • El uso de WebSocket generaba mucho costo computacional, principalmente por la fragmentación y el masking
    • Fragmentación: la implementación de WebSocket de Chromium fragmenta en múltiples frames los mensajes mayores a 131 KB. Un frame de video raw de más de 3 MB terminaba dividido en más de 24 frames separados
    • Masking: por motivos de seguridad, WebSocket aplica masking a todos los frames enviados del cliente al servidor. Con volúmenes de más de 100 MB por segundo, esto se vuelve un overhead significativo

Búsqueda de alternativas

  • Como con las APIs del navegador era difícil implementar algo con mucho mejor rendimiento que WebSocket, decidieron hacer un fork de Chromium e implementar una función personalizada
  • Consideraron 3 alternativas: raw TCP/IP, Unix Domain Socket y Shared Memory
    • TCP/IP: evita los problemas de fragmentación/masking de WebSocket, pero el tamaño máximo de paquete es pequeño, así que la fragmentación sigue existiendo. Además, hay overhead por la copia hacia espacio de kernel
    • Unix Domain Socket: permite saltarse por completo el stack de red, pero aun así requiere copiar datos entre espacio de usuario y espacio de kernel
    • Shared Memory: memoria a la que varios procesos pueden acceder al mismo tiempo. Chromium puede escribir directamente en la memoria compartida y el codificador leerla de inmediato, sin copias intermedias

Implementación de transporte basada en memoria compartida

  • Implementaron la memoria compartida con forma de ring buffer para leer y escribir datos de manera continua
  • Requisitos: lock-free, múltiples productores/un solo consumidor, tamaño de frame variable, lectura zero-copy, compatibilidad con sandbox y señalización de baja latencia
  • Evaluaron implementaciones existentes de ring buffer, pero como ninguna cumplía todos los requisitos, decidieron crear la suya
  • Para soportar lectura zero-copy, dividieron los punteros en tres: write, peek y read
  • Para garantizar seguridad entre hilos, usaron operaciones atómicas y, para avisar cuando había datos nuevos o espacio libre, usaron named semaphores
  • Con la implementación del ring buffer basado en memoria compartida y otras optimizaciones, lograron reducir hasta en 50% el uso de CPU de los bots. Al final, ahorraron más de un millón de dólares al año en costos de AWS.

3 comentarios

 
GN⁺ 2024-11-08
Comentarios de Hacker News
  • Esta es la historia típica de una startup que elige un atajo "suficientemente bueno" y luego optimiza más adelante.

    • En una empresa había un clúster de VM con alto uso de CPU, y usaron un profiler para optimizarlo.
    • Redujeron el uso de CPU eliminando datos antiguos y agregando filtros a las consultas.
  • Hay comentarios de sorpresa por el alto ancho de banda de los datos de video en bruto.

    • Critican las decisiones de diseño de WebSockets y que no anticiparan el problema del uso de CPU.
  • Hay opiniones de que no fue un problema de AWS, sino de desperdiciar ciclos de CPU.

    • WebSockets está relacionado con la transferencia de datos o con los costos de API Gateway.
  • Señalan que el MTU y el MSS de las redes TCP/IP son pequeños en comparación con el tamaño de los frames de video.

    • Afirman que hace falta conocimiento técnico y que necesitan contratar desarrolladores.
  • Hay quien opina que usando Mojo de Chromium no tendrían que preocuparse por código específico de cada plataforma.

    • También consideran aceptable implementar un ring buffer personalizado.
  • Hay comentarios de que el problema no era la red, sino la falta de comprensión sobre los códecs de video.

    • Dicen que no entienden por qué no usaron un protocolo de streaming de video como RDP.
  • Elogian la transparencia y dicen que también les gustaría ver transparencia en el precio del producto.

  • Explican que el masking del protocolo WebSocket fue un intento de resolver problemas de intermediarios.

    • Dicen que vale la pena leer el RFC relacionado.
  • Señalan que es extraño transmitir datos de video sin comprimir.

    • Dicen que no entienden por qué no enviaban un stream comprimido.
  • Comentan que les sorprendió el enfoque inicial de transmitir video en bruto por WebSocket.

    • Dicen que la ineficiencia no impidió el desarrollo del producto.
    • Dicen que no entienden un enfoque que no toma en cuenta la cantidad de datos.
 
ahwjdekf 2024-11-09
  • Considero que al desarrollar el producto no se tuvo en cuenta para nada el rendimiento.
  • Al final, este problema se reduce a cómo hacer IPC con grandes volúmenes de datos.
  • La diferencia es que no se trata de un IPC común, sino de hacer IPC con el navegador Chrome, y
  • aunque el funcionamiento interno de Chrome no debe ser tan sencillo, como es abierto se puede modificar.
  • Entonces, al final, es un problema de elección de IPC.

Desde el principio lo desarrollaron mal...

 
ahwjdekf 2024-11-09

"Dicen que el enfoque inicial de transmitir video sin procesar por WebSocket es sorprendente." Coincido con eso.