Bug Tracker

Opened 6 years ago

Closed 6 years ago

#14042 closed bug (wontfix)

Memory leak after running .data() on unattached elements

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

Description

Demo here : http://jsfiddle.net/futjE/

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.

Change History (3)

comment:1 Changed 6 years ago by dmethvin

Cc: Rick Waldron added
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.

comment:2 Changed 6 years ago by Rick Waldron

Owner: set to Rick Waldron
Status: openassigned

Thanks for the report, patch coming soon.

comment:3 Changed 6 years ago by Rick Waldron

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:

http://gyazo.com/a94338944a6a026f7c1f2dd62824dac1.png

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.

Note: See TracTickets for help on using tickets.