Skip to main content

Bug Tracker

Side navigation

#14042 closed bug (wontfix)

Opened June 19, 2013 10:40PM UTC

Closed June 24, 2013 03:28PM UTC

Memory leak after running .data() on unattached elements

Reported by: acre88 Owned by: rwaldron
Priority: high Milestone: None
Component: data Version: 2.0.2
Keywords: Cc: rwaldron
Blocked by: Blocking:

Demo here :

Mac OS X 10.8 (latest), Chrome 27.

There are probably a bunch of ways to go about testing this. Please feel free to improve.

I create an unattached element -- jQuery( "<div>...</div>" ) -- and then do a .find(*) to get all its descendants. If I loop over each of those descendants and try to get .data( "name" ), it seems to set up a reference to the unattached element which is not getting released. If you run the loops enough times, memory usage piles up.

If you run the same loop without the .data( "name" ) part, memory doesn't leak.

I tested in 2.0.1, 2.0.2 and 1.8.1, but I assume it's there in other versions too. Memory leaking is much more significant in 2.x.

I use Chrome's heap snapshot tool to get memory usage stats. When I run it, the app stabilizes at about 3 megs of memory after loading (higher on jsfiddle). Running the first test jumps memory to 9 megs in 1.8.1 and about 40+ megs in 2.0.2. Running the second test doesn't increase memory usage.

Attachments (0)
Change History (3)

Changed June 23, 2013 04:29PM UTC by dmethvin comment:1

cc: → rwaldron
component: unfileddata
priority: undecidedhigh
status: newopen

The 1.x data code only creates an object when data is set, or when the caller asks for the whole data object. The 2.x code always creates data on a query, which we should avoid.

This specific case is a bug, but in general we can't ensure that data is removed on detached elements (we don't know when you're done with them). So you'd need to call .remove() on the elements for the more general case of setting data on detached elements, which would also work for this case to fix the leak.

Changed June 23, 2013 06:51PM UTC by rwaldron comment:2

owner: → rwaldron
status: openassigned

Thanks for the report, patch coming soon.

Changed June 24, 2013 03:28PM UTC by rwaldron comment:3

resolution: → wontfix
status: assignedclosed

My first "hunch" in working through this issue lead me directly to the answer, which is that jQuery's data API has always done this. When I was working on data for jQuery 2 I encountered an unfortunate expectation of the "get" semantics: When data is requested from an element that doesn't yet have data, that element is automatically _given_ an empty data object.

To illustrate, I ran the test cases in both 2.x and 1.x, here are the results:


Snapshot 1: This is jQuery 2.x before any tests are run.

Snapshot 2: This is jQuery 2.x after the first test is run.

Snapshot 3: This is jQuery 2.x after the second test is run.

(A page refresh occurred here)

Snapshot 4: This is jQuery 1.x before any tests are run.

Snapshot 5: This is jQuery 1.x after the first test is run.

I didn't bother running the second test for jQuery 1.x because the information it provides is irrelevant in either case.

For fun, I modified the get method to avoid the creation path and it broke a lot of tests.