I am the developer of the @bannsaenger/node-red-contrib-artnet-controller.
This node uses a timer mechanism to handle transitions where values are send in specific timing. Therefor i use the setTimeout like:
this.mainWorker = setTimeout((function() {
.. do stuff here
}.bind(this)), this.senderClock);
and this.mainWorker.refresh() for continuation because the timer has not to run ever.
If senderClock is less than 30ms, the mainWorker is called every 30ms. If i set it to 50ms it is called every 60ms.
It seems like the main eventloop runs only every 30ms.
Can this be configured? I cant find a setting in settings.js
Node.js timers are not real-time and only guarantee a minimum delay. The callback runs when the event loop is free, so under load (or due to OS timer resolution) you will see jitter and drift. There is no setting in Node-RED or Node.js to configure the event loop frequency.
If you need tighter timing guarantees (e.g. consistent <30ms intervals), Node.js is not deterministic enough for that use case. For most Node-RED flows, timing should be treated as approximate rather than exact.
Even if you wrote the timing part in a non garbage collected lang (like rust or C) you are still at the mercy of the OS scheduler / Kernel timer resolution / Process scheduling latency / Interrupts / CPU load
If you genuinely need consistent sub-30 ms precision with low jitter, the correct answer is to use a real-time system (e.g. PREEMPT_RT Linux) or move this code to a microcontroller
instead of using times, can you not make this event based? e.g. x happens, do y instead of polling at hight speed?
Steve is, of course , completely correct in his assessment. However, there is one possible thing that might help if you really must use a rapid setTimeout (though I agree fully with Steve, event-driven is by far a better way to go if you can).
That is to create a worker thread. These became stable in node.js in v12. A worker thread has its own instance of the v8 engine and its own loop.
However, as already indicated, if your issue is actually that the underlying hardware is CPU-bound, this probably won't help too much.
I've done some other projects in Node.js with the use of such timers.
You are right with the jitter and that the timing isn't as precise, but in all my other projects the resolution is not bound to 30ms or something like that.
This must be a restriction in the core of Node-RED.
Node-RED does not (cannot) impose a minimum timer resolution. It uses the standard Node.js timer APIs, and their behaviour is determined by Node.js, libuv and the host OS.
What can happen:
If the flow is busy (lots of nodes executing, any synchronous work, CPU heavy loads), the event loop may not return to the timers quick enough.
If a node blocks (e.g. synchronous ops, filesystem ops, tight non-async loops), timers will be delayed.
If the system is under load, you’ll also see drift.
But thay ^ resulty in event loop delay (not a 30 ms floor).
PS: Using worker threads wont (completely) solve the underlying issue (tho they might improve regularity since they have their own event loop). Workers still use the same OS scheduler / libuv timer implementation / are still non-real-time