How to debug/avoid memory leaks in your application

Modified on Tue, 21 May at 11:18 AM

Recognize

When you experience crashes or poor performance from your LuvitRED application, chances are that your application has a memory leak. This can especially happen in flows with custom Lua code in Function nodes. When you experience this behavior, there are some key things you can do. Prevention is more important than debugging, so please always keep the following points in mind when developing a LuvitRED flow.


Avoid/Prevent

  • Always use local variables, unless you really need a global variable
  • Do not use infinite loops
  • _u.deepcopy() tables when you want a local variant of a table (and all its sub levels)
    http://lua-users.org/wiki/CopyTable
  • Avoid flow wide globals and preferably transfer data using the msg object
  • Clear your flow wide globals when not needed anymore


Lint Check

Starting from LuvitRED 2.24.2 you can lint check your own lua code in your function and module nodes.

 

Drag a "flow" node into your flow and enable the lint check checkbox.

This will perform a lint check every time the flow starts, ie on a redeploy or when the cloudgate boots.

Any lint warnings from function nodes will be printed as warnings in the debug tab.


If you need variable names that you don't need, use the underscore "_" variable. Example:


for _, val in ipairs(msg.table) do
    p(val)
end



Warning: this can be relatively slow, so only enable the lint check when you are checking for issues, when your flow is completed remove the lint checking.


For example, if a function "fun1" contains the following code:


a = true


Then a warning like the following image will appear:



If you wish to ignore any warnings, then read the documentation provided here:

https://luacheck.readthedocs.io/en/stable/inline.html


For example the code:

-- luacheck: globals a
a = true
b = true


Will give no warning for the global variable a, but will give a warning for the global variable b.



Debug

Use the flow node to print the memory usage on a hourly basis. In the debug node you can select to output the msg to the console so that you can later download a CloudGate log file with the memory usage.


Example output in the CloudGate log:


[debug:memory] {"heapUsed":4001241,"rss":15265792,"total":128004096,"free":54640640}
[debug:memory] {"heapUsed":4002545,"rss":15204352,"total":128004096,"free":54697984}
[debug:memory] {"heapUsed":4008137,"rss":15208448,"total":128004096,"free":54697984}
[debug:memory] {"heapUsed":4017097,"rss":15212544,"total":128004096,"free":54697984}


"HeapUsed" is the memory (in bytes) used by the LuvitRED process. That includes your flow. If this parameter keeps rising, then this is an indication of a memory leak. After some hours you can download the log file and make a chart of the heapUsed. 


In the example below the customer started having issues after the luvitred memory usage exceeded 27 MB.



The "flow" node can also be used to restart the LuvitRED flow (not the LuvitRED process or the CloudGate) on a regular basis, e.g. daily at midnight. Doing this and logging the memory usage as before allows you to determine if the memory leak is likely to be inside the flow or inside a LuvitRED node. If you determine the memory leak is inside LuvitRED itself, we kindly request to create a ticket on https://support.option.com/support/tickets.


To debug your application you can monitor your device status in the Command Line Interface using the 'top' command. 


By periodically writing your tables to the debug screen you can get a clear image of the state of your table variables and their size. If your application performs actions on a certain interval, try to increase the interval to increase the speed of the memory increase. 


If you use some global variables, try printing the entire global table to a debug node. 

In a function node you can do the following:


msg.payload = global

return msg



Locked out, now what?


When you create an infinite loop, or your application keeps crashing, chances are that you locked yourself out of LuvitRED. If you do not have a backup you lost your flow. You can still export your config and contact Option for assistance, we can extract your flow out of this exported config file. Please create a ticket on https://support.option.com/support/tickets.


When you are not completely locked out, you might have a small window after reboot that your application is not blocked yet. Use this time window to disable your flow, or the problematic tab in LuvitRED, and redeploy your flow.


Backup

Before making breaking changes to your flow, it's always best to save a local backup to your PC. This way you can always fall back to the latest functioning state. You can do this by selecting the hamburger menu in the top right corner --> Export --> File - All nodes, like shown below:


Was this article helpful?

That’s Great!

Thank you for your feedback

Sorry! We couldn't be helpful

Thank you for your feedback

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article