Cómo se mantiene rápido en un portátil corriente.
Las pantallas de trading pesan: historiales largos, ticks que no paran, muchos gráficos en una página. TradeCanvas hace solo el trabajo que necesita cada fotograma, en el hilo principal y sin código de terceros. Esta página muestra cómo, y dónde aún se está mejorando.
En desarrollo: el motor ya es lo bastante rápido para producción, pero todavía no tanto como lo será. La última sección enumera lo que sabemos que falta.
Paquetes pequeños, en una sola dirección
Cada paquete depende solo de los que tiene debajo. Nada ajeno a TradeCanvas se ejecuta en tu página: los componentes para frameworks reciben React, Vue o Svelte como dependencias peer, y el renderizador WebGL es un fragmento aparte que solo se carga cuando un gráfico lo pide.
0 dependencias de terceros en tiempo de ejecución
El recorrido de un tick
Un precio llega desde tu fuente de datos y alcanza la pantalla en un fotograma. Cada etapa hace solo la parte que cambió.
- 1Tu fuente de datos
DataAdapterWebSocket, REST, un bróker: cualquier cosa con historial y un flujo en vivo. - 2Gestor del flujo
StreamManagerPrimero el historial, luego el directo. Las respuestas a una petición antigua se descartan; una fuente que se queda en silencio se detecta en menos de 30 s. - 3Agregador de ticks
TickAggregatorLos ticks entran en un búfer circular de 1,000 y se incorporan a la barra de su temporalidad. - 4Indicadores
IndicatorEngineSe recalculan desde la última barra, no desde el inicio de la serie. - 5Viewport
ViewportSolo se recorren las barras en pantalla; la escala de precios sale únicamente de ellas. - 6Bucle de renderizado
RenderLoopLleguen los ticks que lleguen, la escena se dibuja como mucho una vez por fotograma de animación. - 7Canvas 2D o WebGL
RenderEngineDos canvas, y un canvas de GPU debajo cuando WebGL está activo.
Un tick cuesta una barra, no todo el historial
Cuando un tick cambia la última barra, cada indicador continúa desde esa barra (y las pocas anteriores que su fórmula consulta) en lugar de recalcular la serie. Si las barras que recuerda ya no coinciden, vuelve a un recálculo completo, así que nunca se pierde una corrección.
Unos 20 indicadores tienen su propia actualización incremental, y otros 31 se basan en una base que continúa punto a punto. Los indicadores que leen la línea de otro indicador también continúan.
Con el zoom alejado: una columna por píxel
Cuando las barras son más estrechas que un píxel, dibujar cada una desperdicia trabajo que el ojo no ve. Las velas, las barras, el máximo-mínimo y el volumen se dibujan como una columna por píxel, con la primera apertura, el máximo más alto, el mínimo más bajo y el último cierre de las barras que caen en ella. Las líneas y las áreas conservan unos dos puntos por píxel (LTTB); las líneas y bandas de los indicadores dibujan un tramo por columna de píxeles.
- barras en pantalla
- 313
- barras por píxel
- 0,39
- formas dibujadas
- 313
Una barra nunca es más estrecha que un cuarto de píxel CSS, así que un gráfico con un millón de barras muestra como mucho unas cuatro barras por píxel con el zoom totalmente alejado: unas 6,400 en un gráfico de 1,600 px. Desplazarse por el resto es lo que mide el benchmark del millón de barras.
Dos canvas, para que pasar el ratón no cueste casi nada
La escena (cuadrícula, series, indicadores, dibujos, órdenes) vive en un canvas; la cruz, la leyenda, las etiquetas de los ejes y la cuenta atrás viven en un canvas fino encima. Mover el ratón solo vuelve a pintar el de arriba. Una actualización de datos vuelve a pintar la escena una vez, en el siguiente fotograma.
Cada canvas a tamaño completo le cuesta al navegador una composición por fotograma, así que el motor usa pocos: un canvas trasero para dibujos solo 2D existe únicamente mientras algo lo necesita.
WebGL grabando, no reescribiendo
El gráfico dibuja con llamadas de Canvas 2D. Con WebGL activo, esas llamadas van a un grabador que convierte trazados, rellenos y trazos en comandos de GPU en píxeles del dispositivo. Lo que la GPU no puede dibujar igual se queda en Canvas 2D, en orden, así que la imagen es la misma en ambos casos.
- trazados, rellenos y trazos
- velas, volumen y cuadrícula como dibujos instanciados
- la serie en un único Float32Array, seis floats por barra; un tick solo reescribe el final
- texto
- imágenes y patrones
- sombras, filtros, recortes inusuales
- todo lo que sigue al primer paso que la GPU no puede dar
renderer: 'auto'pide al navegador un contexto sin advertencia de rendimiento grave, así que una máquina cuyo WebGL funcionaría por software se queda con Canvas 2D.- Como mucho 8 gráficos de una página tienen un contexto WebGL (
setMaxWebGLCharts); los demás esperan en una cola y dibujan con Canvas 2D. - Si la GPU pierde el contexto, el gráfico sigue con Canvas 2D y se reconstruye en WebGL cuando el contexto vuelve.
- Las velas se redondean a píxeles enteros del dispositivo con la misma regla en los shaders y en la CPU, así que ambos renderizadores las ponen en los mismos píxeles.
Hecho para máquinas modestas
- Canvas 2D por defectoWebGL es opcional hasta que se haya medido en más dispositivos. En gráficos integrados con una densidad de píxeles alta, el cuello de botella es la composición del propio navegador, no el dibujo.
- Un redimensionado por fotogramaLos eventos de cambio de tamaño se agrupan en uno por fotograma, y un tamaño que no cambió no hace nada.
- Historial por páginasLas barras antiguas se cargan de 500 en 500 al desplazarte hacia atrás, una petición cada vez, esperando más tras un fallo.
- Sin parpadeos de cargaEl velo de carga espera 200 ms, así que un cambio rápido de símbolo nunca parpadea.
- Poco que descargarEl gráfico sin interfaz ocupa 176 KB con gzip, el widget completo 315 KB y el renderizador WebGL otros 18 KB cuando se usa.
- Pizarras que se actualizan en su sitioLa pizarra de precios de bo-grid agrupa los ticks en un parche por fotograma y solo vuelve a pintar las celdas que cambiaron.