Quantcast
Channel: DeepElement » HTML5
Viewing all articles
Browse latest Browse all 6

HTML5: Snagging Javascript Memory Leaks

$
0
0
Working on high-performance HTML5 applications, I have noticed that one of the most common anti-patterns is the ‘pinning’ of closures to the Visual Tree.
Pinning is a situation where your object graphs stay attached to the Document/Window scope for the lifetime of your HTML5 application
Google Chrome includes a Heap Profile Tool that is invaluable for tracking memory leaks

Example of a Memory Leak caused by Closure Pinning

Consider the following page, which creates a bunch of Components, attaches them to the Document Loaded event and then tries to delete their references:

 

What Chrome Reports

Explanation

Pressing the button creates an Component, which is then ‘attached’ to the page’s Document scope via the loaded event. The key to this leak is the ‘self’ reference in the loaded callback closure. In order for the window to be able to call the pages on ‘future’ loaded events (haha), the Component instances have to be held by the Document. Hence, the Component instances are  ”Pinned” to the Document and the Delete calls do nothing… even NULL’ing out the local reference doesn’t buy the Component it’s freedom to flee. Another important observation is that each Component instance appears to be pretty big; this means that the Component and all of its direct references are hanging around in Memory in relation to the ‘pinned’ closure. In Short:
  • delete keyword does nothing valuable if object has other primary references active
  • nulling item does not release all active references
  • Inactive references carry direct references in context state – which increases the size of the Pinned leak

Proving the Leak by Dereferencing the Self Closure Pinning

Let’s prove this hypothesis by removing the self closure reference, but leaving the loaded event handler

What Chrome Reports

Explanation

In this case, the loaded event is still registered, the Component instances can still receive updates from the Document. The difference is that the Document has no direct reference to the Components themselves, by virtual that the callback can perform without the Component remaning in memory. We can then call Delete and Null on the knowledge holder and the relationship is severed. In Short:
  • delete keyword does release objects to GC if other primary references are not active
  • nulling item does not release reference
  • This proves that the Self context reference in the closure causes the leak
 

Avoiding the Closure Pinning Leak by Managing Relationships

Let’s take an alternative approach to view context Pinning by introducing a life-cycle to the Component Instance

What Chrome Reports

Explanation

The three important additions to the javascript is
  1. We have to bind the ‘this’ context to the handler callback method (see the constructor)
  2. Using JQuery Bind api to observe the document event
  3. Introducing literal Attach and Detach phases to the life-time of the Component Instances
Thanks to Vyacheslav Egorov for pointing me in the right direction about the best way to pass the context to the handler.
 
These combinations allow us to avoid context Pinning to the Visual Tree through the abstraction of the native Javascript call-stack.
In Short:
  • delete keyword does release objects to GC if other primary references are not active
  • nulling item does not release reference
  • Window/document events must be un-registered using context handler
  • Closure scope can be passed safely using the ‘apply’ or ‘call’ syntax in javascript
 

Conclusion

Closures are awesome in that they are wicked-easy, especially when designing Asyncronous API’s. For most historical web sites, closure leaks will be flushed out within a few minutes, swept away by the constant browser refreshes. But, for the HTML5 Architect, always keep track where your Business Layer is ‘Pinned’ to the Visual Tree. This could mean the life, or death, of your application in the long-run. One dangling association could result in massive object graphs staying in memory for the life-time of the Document/Window state, which can be considered Application-scoped for long-term offline applications.

Viewing all articles
Browse latest Browse all 6

Trending Articles