Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

425
Views
¿Cómo se vincula el tiempo de `setImmediate()` y `setTimeout()` con el rendimiento del proceso?

Estoy confundido por el siguiente párrafo de la documentación de Node.js.

setImmediate() frente setTimeout()

... El orden en que se ejecutan los temporizadores variará según el contexto en el que se llamen. Si se llama a ambos desde el módulo principal, el tiempo estará limitado por el rendimiento del proceso (que puede verse afectado por otras aplicaciones que se ejecutan en la máquina).

Por ejemplo, si ejecutamos el siguiente script que no está dentro de un ciclo de E/S (es decir, el módulo principal), el orden en que se ejecutan los dos temporizadores no es determinista, ya que está sujeto al rendimiento del proceso:

Se procede a mostrar el siguiente ejemplo

 // timeout_vs_immediate.js setTimeout(() => { console.log('timeout'); }, 0); setImmediate(() => { console.log('immediate'); });
 $ node timeout_vs_immediate.js timeout immediate $ node timeout_vs_immediate.js immediate timeout

No entiendo qué hace que el resultado no sea determinista. Dado que la fase de timers ocurre antes de la fase de check , ¿no deberían las devoluciones de llamada programadas por setTimeout ejecutarse siempre antes que las programadas por setImmediate ? No creo que el orden de las fases en el ciclo de eventos cambie debido a un cambio de contexto o algo así.

El documento también establece que

Sin embargo, si mueve las dos llamadas dentro de un ciclo de E/S, la devolución de llamada inmediata siempre se ejecuta primero:

Bien, pero ¿qué diferencia a los llamados "ciclos de E/S" del módulo principal?


Sé que hay muchas preguntas relacionadas, pero todas las respuestas simplemente establecen este hecho citando la documentación, sin explicar dónde entra en juego el no determinismo, por lo que no creo que esto sea un duplicado.

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

El truco real está en el constructor Timeout al que llama setTimeout y que aumenta los tiempos por debajo de 1 a 1. Por lo tanto setTimeout(fn, 0) es en realidad equivalente a setTimeout(fn, 1) .

Cuando libuv se inicializa , comienza con los temporizadores después de actualizar su reloj interno, y cuando ya ha pasado un milisegundo, activará el temporizador antes de proceder a la fase de encuesta (que es seguida por la fase setImmediate).


Otra observación interesante es que varios temporizadores también pueden ejecutarse antes y después de setImmeadiate:

 setTimeout(() => console.log('timer'), 1); setTimeout(() => console.log('timer'), 1); setImmediate(() => console.log('immediate')); // can produce: // timer // immediate // timer

Esto se debe a que setTimeout llama internamente a getLibuvNow , que llamará a env->GetNow() y que no solo obtiene la hora actual de libuv, sino que también la actualiza . Por lo tanto, puede suceder que el temporizador se coloque en la cola del temporizador con diferentes tiempos de vencimiento y, por lo tanto, la fase del temporizador solo recogerá algunos de ellos.

Bien, pero ¿qué diferencia a los llamados "ciclos de E/S" del módulo principal?

El módulo principal se ejecuta antes de que se inicialice libuv, mientras que la mayoría de los demás códigos se ejecutarán en la fase de sondeo del bucle libuv . Por lo tanto, la inicialización del módulo principal es seguida por la fase del temporizador, mientras que la fase de sondeo es seguida por la fase de 'controles de verificación', que, entre otras, ejecuta las devoluciones de llamada setImmediate . Por lo tanto, por lo general, en el módulo principal, los temporizadores se ejecutan antes que los inmediatos (si están vencidos) y, si se programan en las devoluciones de llamada, los inmediatos se ejecutan antes que los temporizadores.

about 4 years ago · Juan Pablo Isaza Report

0

También escribiré una respuesta para la visibilidad, ya que es una buena pregunta y la documentación del nodo es engañosa y tuve que investigar un poco para encontrar algunos recursos también...

Esta pregunta se respondió aquí (respuesta aceptada) muy bien con una prueba comparativa de rendimiento.

Pero la explicación real se puede encontrar en otra respuesta que apunta a este artículo que explica mejor el ciclo de eventos.

bucle de eventos explicado

diferencia explicada

Además, lea esta respuesta (esta es la mejor, revisa el código interno y explica qué sección depende de la plataforma y consume mucho tiempo de la CPU y genera el no determinismo y también el hecho de que 0 se transforma en 1 internamente para setTimeout) a un problema planteado en nodejs que hace la misma pregunta que parece explicarlo aún más.

Una cosa más importante a tener en cuenta es que setTimeout cuando se establece en 0 se convierte internamente en 1.

Esta llamada a uv__hrtime depende de la plataforma y consume mucho tiempo de CPU, ya que hace una llamada del sistema a clock_gettime. Se ve afectado por otra aplicación que se ejecuta en la máquina.

Si la preparación antes del primer bucle tomó más de 1 ms, Timer Phase llama a la devolución de llamada asociada. Si es menos de 1 ms, Event-loop continúa con la siguiente fase y ejecuta la devolución de llamada setImmediate en la fase de verificación del bucle y setTimeout en el siguiente tic del bucle.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!