Node-Red consuming 100% CPU

Hello,

I have a strange problem I can not get to the bottom of.

Firstly, I started using Node-Red a long time ago on a project that has morphed and grown, and in retrospect Node-Red ios the wrong approach, it has grown into something of beast with the flow being ~8mB and dashboards with 100's of buttons, 30+ tabs, chromium on a RPI doesn't like it. But it is just too traumatic to change it out at this point. For the most part it runs fine, CPU usage of ~10-25% and memory 20-30%.

So I have a very strange issue where I alter a minor part of the flow and it will go into a state where the CPU goes to 100%. This is a strong indication of there being a infinite loop, but I can not find it in the flow.

The strangest thing is the part of the flow I modify is upstream of the point Node-Red executes to before it goes to 100% and freezes, at least this is what the debug prints tell me. If I remove the upstream flow (that it never gets to) then it works again, no problem.

I am looking for some high level tools or ideas I can use to try and track down what is going on. Debug prints are just not working.

Thanks all.

Are you using mqtt? If so, when it locks up, stop the mqtt server and see if it recovers. That will tell you whether it is an mqtt loop.

Do you mean downstream (ie after)?
One of the problems with working out exactly where a loop is is that debug output is delayed slightly because of the processing involved, and once the loop starts then you may not see the debug output from earlier in the flow. If you temporarily put something like a 100ms delay node after the point where you have the debug node attached then that will make sure that the debug node output appears.

Closing this out incase it helps someone else.

Problem was not MQTT.

Good idea Colin using the delay and print statements, helped me figure out the issue.

I am not exactly sure why this creates a 100% CPU situation, but this portion of code, which had an if loop in a function node, had no issues. It is an if loop that iterates 1 to 10, gets a global variable, splits the string into numbers, then sums the numbers. I do this because I save arrays as strings in SQL.

//extract sum of individual sensor alarms
for (var i = 0; i < room_number; i++) {
    a = ["Alarm_Room_", i + 1, "_1_Timeout"];     
    Alarm_Room_X_1_Timeout = a.join('');        //convert array to string
    b = global.get(Alarm_Room_X_1_Timeout);   //
    c = (b.split(","));                             // its a string, so split it to numbers
    d = Number(c[0]);
    e = Number(c[1]);
    f = Number(c[2]);
    g = Number(c[3]);

    sum_total = sum_total + d + e + f + g;
}

But this section of code did have an issue, the only difference is the number of values I am splitting

//extract sum of individual sensor alarms
for (var i = 0; i < room_number; i++) {
    a = ["Alarm_Room_", i + 1, "_2r_Timeout"];         
    Alarm_Room_X_2_Timeout = a.join('');        //convert array to string
    b = global.get(Alarm_Room_X_2_Timeout);   
    c = (b.split(","));                             // its a string, so split it to numbers
    d = Number(c[0]);
    e = Number(c[1]);
    f = Number(c[2]);
    g = Number(c[3]);
    h = Number(c[4]);
    i = Number(c[5]);
    j = Number(c[6]);
    k = Number(c[7]);
    l = Number(c[8]);
    m = Number(c[9]);
    dd = Number(c[10]);
    ee = Number(c[11]);
    ff = Number(c[12]);
    gg = Number(c[13]);
    hh = Number(c[14]);
    ii = Number(c[15]);
    jj = Number(c[16]);
    kk = Number(c[17]);
    ll = Number(c[18]);
    mm = Number(c[19]);
    ddd = Number(c[20]);
    eee = Number(c[21]);
    fff = Number(c[22]);
    ggg = Number(c[23]);
    hhh = Number(c[24]);
    iii = Number(c[25]);
    jjj = Number(c[26]);
    kkk = Number(c[27]);
    lll = Number(c[28]);
    mmm = Number(c[29]);
    dddd = Number(c[30]);
    eeee = Number(c[31]);
    ffff = Number(c[32]);
    gggg = Number(c[33]);
    hhhh = Number(c[34]);
    iiii = Number(c[35]);
    jjjj = Number(c[36]);
    kkkk = Number(c[37]);
    llll = Number(c[38]);
    mmmm = Number(c[39]);

    sum_total = sum_total + d + e + f + g + h + i + j + k + l + m + dd + ee + ff + gg + hh + ii + jj + kk + ll + mm + ddd + eee + fff + ggg + hhh + iii + jjj + kkk + lll + mmm + dddd + eeee + ffff + gggg + hhhh + iiii + jjjj + kkkk + llll + mmmm
}

:man_shrugging:

My solution was to remove the if loop and just hard code / copy paste the code 10 times in the function node, which is very messy, but is working fine.

I don't think that is a very good idea.

2 Likes

Slightly ironic that in Monaco editor, the only variable name not flagged as undeclared is i!
image

ARGGG!!!!! What an absolute n00b, I completely missed that.

Ironic, perhaps, but i IS defined hence no error :wink:

@dr_cave_dweller do you not see all these hints? They are effectively telling you your code is (for want of better words) "susceptible to bugs"'?

It doesnt slow down Node-RED if you use descriptive variables (Using good var names is good practice - makes code more maintainable)

Monaco editor shows you these squiggles for a reason :man_shrugging:

They are showing up red squiggles because I only pasted part of the node, I didn't bother pasting the part of code declaring variables as I didn't think it was relevant.

Freely admit I am a bad coder. In my defense, this code is 5 years old when I had literally just started learning how to code and I wouldn't do things the same now, but the die has been set on this project.

One benefit of Node-Red at the time was function nodes could be generic and copy pasted to multiple places where the input and output was different, I just had to tweak the name of which global variable I wanted to read in and it outputs a msg to next node for saving. If I made variables truly descriptive then I would have to change 40 variables names in every function node I copied. Sure, I could have used a generic descriptive variable like data1, data2 instead of ccc, ddd etc etc but I didn't and now I need to live with my coding sins.