Estoy trabajando con una API para analizar datos del mercado de valores en NodeJS.
El programa funciona bien hasta alrededor de 30 000 transacciones por segundo, lo que está bien para las partes más lentas del día. Sin embargo, durante la apertura del mercado, puede superar las 100 000 transacciones por segundo y el montón explota a más de 30 GB, retrasándose y finalmente colapsando, a pesar de estar en una máquina extremadamente rápida.
Soy relativamente nuevo en NodeJS, pero el cuello de botella parece ser la siguiente sección de código, que obtuve de un cliente de muestra que se encuentra en una extensión de la clase EventEmitter.
onMessage( data ){ data = JSON.parse( data ) data.map(( msg ) => { if( msg.ev === 'status' ){ console.log('Status Update:', msg.message) } this.emit(msg.ev, msg) })
¿Hay una forma más eficiente de codificar esto que podría dar una mejora de velocidad 2x+? Los bits individuales de JSON son bastante pequeños, como los siguientes:
{ "ev": "T", "sym": "MSFT", "x": 4, "i": "12345", "z": 3, "p": 114.125, "s": 100, "c": [ 0, 12 ], "t": 1536036818784 }
En mis comentarios, sugerí que sacara el bucle data.map()
y lo enviara todo de una vez y luego dejara que el cliente recorriera las piezas individuales:
onMessage( data ){ data = JSON.parse( data ) this.emit("multiMsg", data); }
Entonces, el cliente tendría esto:
socket.on("multiMsg", (data) => { for (const item of data) { // process each item here console.log(item); } });
Si todavía recibe muchas llamadas de onMessage()
a toda velocidad, puede acumularlas durante un breve período de tiempo (el tiempo a elegir depende del retraso de tiempo aceptable para su aplicación). Eso también le permite reducir drásticamente la cantidad de mensajes separados que envía al cliente durante los momentos de mucho tráfico, lo que puede ser muchas, muchas veces más eficiente para el servidor. Por lo tanto, si hubiera recibido 100 llamadas a onMessage()
en 50 ms, esta modificación enviará un mensaje acumulado al cliente, en lugar de 100 mensajes separados al cliente.
He aquí una idea de cómo podría funcionar:
const msgQueueTime = 500; // pick an appropriate time delay here let msgQueue = []; let msgQueueTimer = null; onMessage( data ){ data = JSON.parse( data ) if (!msgQueueTimer) { msgQueueTimer = setTimeout(() => { // send data we have accumulated this.emit("multiMsg", msgQueue); msgQueue = []; msgQueueTimer = null; }, msgQueueTime); } // add data onto our queue array msgQueue.push(...data); }