101

I've been getting more into the internals of the Node.js architecture, and a term I see coming up a lot is "tick" as in "next tick of the event loop" or the function nextTick().

What I haven't seen is a solid definition of what exactly a "tick" is. Based on various articles (such as this one), I've been able to piece a concept together in my head, but I'm not sure how accurate it is.

Can I get a precise and detailed description of a Node.js event loop tick?

rook
  • 5,292
  • 4
  • 36
  • 50
d512
  • 29,226
  • 23
  • 72
  • 100
  • since its "loop" , it means "the next time it loops", so a tick its a whole loop , it ends when no events are triggered and nodejs has looped all to check if any is triggered, "nextTick" it means the next loop after the current one. – Gntem Nov 06 '13 at 21:28

4 Answers4

174

Remember that while JavaScript is single-threaded, all of node's I/O and calls to native APIs are either asynchronous (using platform-specific mechanisms), or run on a separate thread. (This is all handled through libuv.)

So when there's data available on a socket or a native API function has returned, we need a synchronized way to invoke the JavaScript function that is interested in the particular event that just happened.

It's not safe to just call the JS function from the thread where the native event happened for the same reasons that you'd encounter in a regular multi-threaded application – race conditions, non-atomic memory access, and so forth.

So what we do is place the event on a queue in a thread-safe manner. In oversimplified psuedocode, something like:

lock (queue) {
    queue.push(event);
}

Then, back on the main JavaScript thread (but on the C side of things), we do something like:

while (true) {
    // this is the beginning of a tick

    lock (queue) {
        var tickEvents = copy(queue); // copy the current queue items into thread-local memory
        queue.empty(); // ..and empty out the shared queue
    }

    for (var i = 0; i < tickEvents.length; i++) {
        InvokeJSFunction(tickEvents[i]);
    }

    // this the end of the tick
}

The while (true) (which doesn't actually exist in node's source code; this is purely illustrative) represents the event loop. The inner for invokes the JS function for each event that was on the queue.

This is a tick: the synchronous invocation of zero or more callback functions associated with any external events. Once the queue is emptied out and the last function returns, the tick is over. We go back to the beginning (the next tick) and check for events that were added to the queue from other threads while our JavaScript was running.

What can add things to the queue?

  • process.nextTick
  • setTimeout/setInterval
  • I/O (stuff from fs, net, and so forth)
  • crypto's processor-intensive functions like crypto streams, pbkdf2, and the PRNG (which are actually an example of...)
  • any native modules that use the libuv work queue to make synchronous C/C++ library calls look asynchronous
josh3736
  • 131,871
  • 30
  • 208
  • 255
  • 3
    Yeah you nailed this. The copying of the queue and running through all the events on the copy was what I was specifically wondering about. Makes a lot of sense now though. Thanks. – d512 Nov 07 '13 at 23:09
  • Is this the famous "Asynchronous Iteration pattern" algo ? – Stef Feb 26 '14 at 16:59
  • @Stef: [That](http://metaduck.com/01-asynchronous-iteration-patterns.html) is about writing regular JavaScript loops where a function call in the loop body contains an asynchronous callback. This post is about how node/V8 implements the *event loop* concept. – josh3736 Feb 26 '14 at 18:08
  • @josh3736 When javascript main thread is infinitely in this while(true) block when is it doing its regular job beyond handling events? – sanjeev Aug 13 '14 at 10:51
  • 1
    @sanjeev, what do you mean by "regular job"? The only thing an ongoing JavaScript application does is process events. – josh3736 Aug 13 '14 at 17:34
  • Thanks @josh3736. Coming from java world, this clarifies a lot. Honestly I have been reading event-driven nature of JS but it never occurred to me that event processing is all it does. – sanjeev Aug 26 '14 at 10:31
  • This a great post but the best explanation I've read is here http://blog.carbonfive.com/2013/10/27/the-javascript-event-loop-explained/ – screenm0nkey Sep 30 '14 at 07:20
  • 2
    I'd like to add that in 0.10.x `setImmediate` will also enqueue a function. – DanielKhan Apr 28 '15 at 13:24
  • What is `lock (queue) { ... }`? – Green Aug 18 '15 at 12:53
  • @Green it's thread synchronization construct I [borrowed from C#](https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx). – josh3736 Aug 19 '15 at 23:19
  • 2
    Does tick mean event loop phase ? – faressoft May 14 '16 at 19:34
  • If there are no more events/messages on the event queue, then the `lock` procedure should block correct? And this is a good time for the OS to context switch out the Javascript thread, and run something completely different. The OS can wake up the javascript thread if something signals the OS to do so "interrupt-driven" (which can be a different thread or process), or if the `lock` procedure was polling-driven. – CMCDragonkai Jun 29 '16 at 14:10
  • @josh3736, Does all the events accumulated in the event queue copied at once in the single turn of the event loop as shown in your code or only a single event is copied in the single turn ? From what i have saw in this video ( youtu.be/8aGhZQkoFbQ?t=20m2s ) only a single event is copied in a single turn. – bhavya_w Nov 21 '16 at 17:14
  • @josh3736 [Here](https://stackoverflow.com/a/37231274/4695280) you sad, that tick is a phase. Documentation says, that there few phases, such as _check_, _timers_, etc. So, `setInterval()`, `setImmediate()`, `setTimeout()` triggering, _poll_ phase (triggering callbacks for new http-connection, db-response, file reading completion), etc... - all of them are ticks? Have I understood you correctly: **phases, listed in docs (timers, I/O callbacks, idle, poll, check, close callbacks), are ticks**? – Boolean_Type Aug 23 '17 at 21:49
  • *Phases* are part of a *tick*. Put another way, a *tick* or *turn* is a single iteration of event loop; inside that iteration, many things happen (timers, I/O, etc), which are divided into *phases*. – josh3736 Aug 23 '17 at 22:22
  • It doesn't really runs in different thread, event loop runs in same thread – Mukul Jain Jun 30 '18 at 16:45
  • Hi, are they the same thing for event queue and callback queue? – hguser May 18 '21 at 06:03
  • There's nothing says the length of a tick. I think a tick is to finish everything in that queue, no matter how long the queue is. After the queue is finished, it starts a new tick. From what i can understand, it provides a way to not run everything at the same time. Inside the same tick, everything is sync. But we refer async as adding things to next tick. – windmaomao Aug 17 '21 at 13:53
  • @windmaomao: Correct. The queue is emptied on every tick, and the next tick may or may not have additional things to process. – josh3736 Aug 18 '21 at 20:30
  • Node JS isn't single-threaded. It uses a thread pool. – Quesofat Apr 12 '22 at 18:38
  • @Quesofat Well said! The Event Loop is single-threaded, but Node on its whole has a thread pool to delegate stuff to. – ankush981 Jun 04 '22 at 08:01
13

A simpler answer for those new to JavaScript:

The first thing to understand is that JavaScript is a "single-threaded environment". This refers to JavaScript's behavior of executing your blocks of code one at a time from "the event loop" on a single thread. Below there's a rudimentary implemenation of the event loop taken from Kyle Simpson's book ydkJS and afterwards, an explanation:

// `eventLoop` is an array that acts as a queue (first-in, first-out)
var eventLoop = [ ];
var event;

// keep going "forever"
while (true) {
    // perform a "tick"
    if (eventLoop.length > 0) {
        // get the next event in the queue
        event = eventLoop.shift();

        // now, execute the next event
        try {
            event();
        }
        catch (err) {
            reportError(err);
        }
    }
}

The first while loop simulates the event loop. A tick is the dequeuing of an event from the "event loop queue" and the execution of said event.

Please see the response of 'Josh3796' for a more detailed explanation of what happens in the dequeuing and execution of an event.

Also, I recommend reading Kyle Simpson's book for those who are interested in getting a deep understanding of JavaScript. It's completely free and open-source and can be found at this link: https://github.com/getify/You-Dont-Know-JS

The specific section I referenced can be found here: https://github.com/getify/You-Dont-Know-JS/blob/2nd-ed/sync-async/ch1.md

Sandeep Patel
  • 4,261
  • 2
  • 18
  • 33
Parm
  • 487
  • 5
  • 16
  • 3
    This kind of confuses me as this answer makes me feel there is just one Queue. And only in that queue dequing one event is considered one tick. Where from some other sources of Internet I see tick means processing all events in the queue of a single phase. – Ayon Nahiyan Feb 18 '21 at 10:01
2

Very simple and short way of Event Loop tick is:

It is used by node internal mechanism where when set of requests on a queue is processed then tick is initiated which represents the completion of a task

Aks
  • 940
  • 2
  • 9
  • 24
1

A "tick" refers to a complete pass through the event loop. Confusingly, setImmediate() takes a tick to run, whereas process.nextTick() is more immediate, so the two functions deserve a name swap.

NagRaghav
  • 11
  • 2