{"id":7896,"date":"2023-08-02T07:33:22","date_gmt":"2023-08-02T06:33:22","guid":{"rendered":"https:\/\/www.scichart.com\/?post_type=blog_scichart&p=7896"},"modified":"2023-12-19T15:45:26","modified_gmt":"2023-12-19T15:45:26","slug":"debugging-javascript-webassembly-memory-leaks","status":"publish","type":"blog_scichart","link":"https:\/\/www.scichart.com\/blog\/debugging-javascript-webassembly-memory-leaks\/","title":{"rendered":"Debugging JavaScript and WebAssembly Memory Leaks using the SciChart.js debug tools"},"content":{"rendered":"
One of the decisions we took when building SciChart.js \u2013 our high-performance JavaScript chart library<\/strong><\/a> \u2013 was to pioneer the use of WebAssembly<\/a> with JavaScript. This allowed us to reuse our C++ code base targeting OpenGL and WebGL which had already been well tested on our windows and mobile versions of SciChart, and bring our award-winning technology into the browser.<\/p>\n The main benefits of our unique tech stack are not only code-reuse and efficiency, but also enabling extremely performant charts & data visualisation for our users. SciChart.js is the fastest JavaScript chart library<\/strong><\/a> available for plotting big data, and in some cases outperforms traditional HTML5 Canvas or SVG charts by over 100x. SciChart enables a whole host of applications in JavaScript: such as embedded systems, scientific applications and medical applications, that were previously impossible. Having a faster chart component also means more it’s efficient: the library can be run on devices with lower power processors, meaning a cheaper cost of production for embedded systems.<\/p>\n The technology of WebAssembly<\/a> with JavaScript is fantastic, but it doesn’t come without its challenges which we will go into below, and then talk about our solutions.<\/p>\n WebAssembly has a completely different memory model to JavaScript. While JavaScript has a garbage collector, which automatically cleans up the memory of variables which are no longer required, WebAssembly simply does not. An object or buffer declared in Wasm memory must be deleted by the caller, if not a memory leak will occur. Memory leaks can occur in both JavaScript and WebAssembly, and care and attention must be taken by the developer to ensure that memory is correctly cleaned up when using SciChart.js.<\/p>\n Despite being a Garbage-Collected managed programming language, it’s still extremely easy to create a memory leak just in vanilla JavaScript. Here are a couple of ways that is possible to inadvertently leak memory in a JavaScript app:<\/p>\n Wasm has a separate heap to the JavaScript virtual machine. This memory is allocated in the browser, and reserved from the host OS. When you allocate memory in Wasm, the Wasm heap is grown and a range of addresses are reserved. When you delete memory in Wasm, the heap does not shrink and memory is not returned to the host OS<\/strong>. Instead the memory is simply marked as deleted or available. This means it can be re-used by future allocations.<\/p>\n To cause a memory leak in WebAssembly you simply need to allocate memory and forget to delete it. Since there is no automatic garbage collection, finalisation or marking memory as no longer needed, it must come from the user. SciChart.js has a function .delete()<\/strong> on objects that use Wasm memory. This needs to be called when the object is no longer required, for example:<\/p>\n This brings a new challenge to JavaScript developers using SciChart.js as it is simply not commonplace to have to manage and delete memory when building a JavaScript application. Forgetting to call .delete()<\/strong> in your application can over time leak memory.<\/p>\n To add to this, we recently learned much more about the WebAssembly memory model. In the current version of WebAssembly, allocation and deletion of memory is more basic than counterparts like Java or C#.<\/p>\n Wasm’s memory model, if used incorrectly, can result in memory fragmentation. Imagine that you allocate an array of 10,000 numbers (64-bit floating point values). This requires 80,000 bytes of continuous memory to be available. Once you have finished with the buffer and you delete it this memory is now marked as free and can be reused. However if you now need to allocate an array of 11,000 numbers, requiring 88,000 bytes of continuous memory, it will not fit into the previous space. So the Wasm heap must grow in size to 168,000 bytes. Over time, memory can become fragmented and you can end up with a large heap of allocated memory in WebAssembly that cannot be fully utilised.<\/p>\n C# .NET and Java solve this by having heap compaction during garbage collection. When the GC is run, periodically the entire application execution is paused, and the heap is defragmented or compacted. This keeps memory usage low, but at the expense of your application stuttering momentarily. We recently learned that WebAssembly does not compact the heap, so we have to be extra careful about allocations and deletions and use of memory in order to keep your application running smoothly.<\/p>\n SciChart.js v3.2 ships with a number of memory debugging tools<\/a> that can notify you if you have incorrectly cleaned up variables, or forgotten to delete WebAssembly memory or objects that have been declared.<\/p>\n Read the full guide over at the SciChart.js Documentation: Memory Leak debugging<\/a><\/p><\/blockquote>\n Enabling memory leak debugging is possible by setting the static property\u00a0MemoryUsageHelper.isMemoryUsageDebugEnabled<\/a>\u00a0= true.<\/p>\n After enabling the memory usage helper you should see a message in the console output like this:<\/p>\n<\/div>\n <\/p>\n Once\u00a0MemoryUsageHelper<\/a>\u00a0is enabled, the memory usage debugging tool has two features:<\/p>\n This allows you to track the state of the registry and be notified on stray objects that have either not been garbage collected (where the solution is to ensure all references to that object have become detached), or be notified of objects that you’ve forgotten to delete (where the solution is to call .delete()).<\/p>\n You can then get the state of the object registry at any time by calling:<\/p>\n Now read the Chrome Dev tools console to uncover reasons for leaked Wasm memory.<\/p>\n <\/p>\n Above<\/strong>: Sample screenshot from SciChart.js’ JavaScript memory leak detection tool. For more info see Documentation: Memory Leak Debugging<\/a><\/em><\/p>\n We’ve made a few other improvements in SciChart.js v3.2 and above, in how we handle memory, making this the most efficient version of SciChart.js ever.<\/p>\n SciChart.js is now available with a FREE community edition<\/strong><\/a> (no trial, sign-up or credit card required) where you can try out the library commercially or use it in a non-commercial application. If you have a question, or would like to give feedback, contact us.<\/p>\n CONTACT US<\/a>GET SCICHART.JS FREE<\/a><\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":" One of the decisions we took when building SciChart.js \u2013 our high-performance JavaScript chart library \u2013 was to pioneer the […]<\/p>\n","protected":false},"author":37,"featured_media":8114,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","blog_scichart_tag":[11,15],"acf":[],"yoast_head":"\nJavaScript vs. WebAssembly Memory Model<\/h2>\n
How Memory Leaks are caused in JavaScript<\/h3>\n
\n
How Memory Leaks are caused in WebAssembly<\/h3>\n
\/\/ Create a SciChartSurface\nconst { wasmContext, SciChartSurface } = await SciChartSurface.create("divId");\n\n\/\/ Add axis and series\nsciChartSurface.xAxes.add(new NumericAxis(wasmContext));\nsciChartSurface.yAxes.add(new NumericAxis(wasmContext));\n\nsciChartSurface.renderableSeries.add(new FastLineRenderableSeries(wasmContext, {\n dataSeries: new XyDataSeries(wasmContext, { \n xValues: [0,1,2,3], \n yValues: [4,5,6,7] \n })\n});\n\n\/\/ When finished with the chart ... \n\/\/\n\nsciChartSurface?.delete();\nsciChartSurface = undefined;<\/code><\/pre>\n
Memory Fragmentation in WebAssembly<\/h3>\n
Detecting Memory Leaks in JavaScript<\/h2>\n
Enabling Memory Leak Debugging Tools<\/h3>\n
import { MemoryUsageTracker } from "scichart";\n\nMemoryUsageHelper.isMemoryUsageDebugEnabled = true;<\/code><\/pre>\n
Tracking Undeleted Objects<\/h3>\n
\n
MemoryUsageHelper.objectRegistry.log();<\/code><\/pre>\n
Other Improvements in SciChart.js Memory handling<\/h2>\n
\n
\n
Start using SciChart.js Today<\/h2>\n