My implementation of the Kendo Grid has a 30 seconds refresh interval. When an interval elapses the Kendo Grid’s Datasource is refreshed from the web server and a dataBound() event handler is triggered. The dataBound() event handler creates elements for the newly fetched data and binds them to the DOM. In the dataBound() event handler we attach several event handlers to these newly created DOM elements. I use these event handlers to show dialogs and such when the user clicks on a cell in the Kendo Grid.
The memory leak occurs when the Kendo Grid is refreshed. On a refresh the Kendo Grid removes the elements from the DOM that were previously added during the last dataBound() invocation. Kendo does not dispose of these elements as expected. Specifically, the event handlers that were previously attached to these elements are not “told” that the elements were removed. This causes a memory leak because the event handlers are retained in memory indefinitely. Every refresh of the Kendo Grid causes another generation of these event handlers to be retained.
Fortunately, fixing the leak is easy. You just need to detach every event handler prior to removing the DOM element to which it is bound. Wen using the Kendo Grid you want to attach your event handlers in the dataBound() event. You want to detach your event handlers in the dataBinding() event. If you use JQuery’s .on() to attach an event handler ( this includes .click(), change(), etc…) you need to use .off() to detach it. If you use JQuery’s .bind() to attach an event handler you need to use .unbind() to detach it.
I’ve created a couple of examples to demonstrate the before and after effects of properly handling this memory leak. The initial source code is taken directly from Kendo’s Demo Site. I have attached a .click() event handler in the Kendo Grid’s dataBound() event handler. The .click() event simply displays an alert pop-up whenever a user clicks on a cell in the table. This is the jsFiddle portraying the memory leak. If I detach the .click() event handler in the Kendo Grid’s dataBinding() event handler the memory leak disappears. This is a jsFiddle with the “fix” applied.
This is the memory footprint of each jsFiddle over a 20 minute period. The green line portrays the memory leak. The red line portrays the “fix”. The memory leakage is around 100-200 kb every 10 minutes.
For a long-running single-page application this is not good. Moving forward I now make memory profiling part of my testing regime. Please let me know if you have any questions.
- The JQuery .empty() function is supposed to recursively remove all child elements as well as detach all event handlers. I have not looked at the Kendo Grid source code. However, if .empty() were being called to dispose of obsolete elements upon a Datasource refresh I would expect this memory leak to not occur.