-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Debugging Tips
This page will eventually become part of the espruino.com docs - please share your debugging tips here!
Bangle.js apps (particularly clocks) have all the code inside { ... }
and use let/const
to define vars, which means none of their code is defined at the global scope and is easy to free (for fast load). When debugging you may want to remove those outer brackets so you can actually check the contents of those variables (and run the functions) from the REPL.
Espruino has a built-in line-by-line debugger that can be triggered by adding the debugger
keyword in your code. More info at https://www.espruino.com/Debugger
If some code crashes or misbehaves, make sure you try running it when connected to the Web IDE. Often an error will produce a stack trace on the IDE's console that will point you to the exact error. If the line numbers aren't correct try disabling pretokenisation and minification in the App Loader/Web IDE and re-upload to ensure that the code on the device is exactly the same as your code.
If the crash is happening when you can't be connected to the IDE you can also set Settings -> Utils -> Debug
to Log
, and you can then connect with the IDE at a later time and load the file log.txt
from the Storage
menu.
If you're using Espruino (not Bangle.js) there are some examples of saving errors that occur when you're not connected here
Espruino stores normal arrays as 'sparse' arrays - so each entry uses one variable. If you want to store any more than 20 items in an array, consider using types arrays like Uint8Array
- they use less memory and are faster more info here.
If you type process.memory().usage
on the console it'll show you how many JS variables are used. The first time you run it it'll add one variable's worth of memory usage (as process
gets allocated), but ideally in most code if check memory usage every so often, the value you get shouldn't keep rising.
Many clocks have a draw()
function and you can call that function manually and then call process.memory().usage
and see if memory goes up. You can sometimes narrow it down to some other function that when called increases memory usage.
You can use E.getSizeOf(global,1)
which will return an array of all the contents of the global
object and how big they are (however the size
values can sometimes be confusing as objects often end up interlinked). You can then try and recreate the memory leak and run E.getSizeOf(global,1)
again, and can compare to see if one of the size
s has got bigger. You can narrow it down by specifying what you're interested in instead of just global
, or can specify E.getSizeOf(global,2)
to provide a multi-level array that digs down further into the structures.
Advanced: you can dump all variables, one per line with E.dumpVariables
(you may have to enable logging in the IDE to capture all the lines). It's then possible to compare the two dumps with a diff
tool to see if there are any new variables defined. Tracking down what a variable corresponds to get be tricky.
You can also use EspruinoMemView - this is a web app that connects to your device, calls E.dumpVariables
and shows you the contents of memory in a graphical format. It can help you find areas of your code where a lot of memory is used.
There are some good examples of testing at https://www.espruino.com/Bangle.js+Fast+Load#testing-afterwards
After you've unloaded an app, you can run dump()
which attempts to dump the contents of RAM in a human readable form - you may be able to see some variables/functions defined there that look like they shouldn't be. It may help to uninstall all widgets first to ensure that they're not making it harder to find the real source of memory usage.
Do you have a variable that's been written, but you don't know where from? You can redefine it as a setter which throws an error, and it will then create a stack trace next time it is set. In this example we're testing width
on the global
object.
Object.defineProperty(global, "width", { set: () => { throw new Error("tried to set width"); } })