New issue
Advanced search Search tips

Issue 822249 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue v8:2869
Owner:
Closed: Mar 2018
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 2
Type: Bug



Sign in to add a comment

Memory leak when using string functions in XHR event handler (and some workaround)

Reported by briz...@gmail.com, Mar 15 2018

Issue description

UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36

Steps to reproduce the problem:
1. Open any site with available big file to avoid CORS issues (only to show bug obviously)

2. Open Developer console and enter following code:

var st=[],NN=100,myval=16; //or st=""
var xh = new XMLHttpRequest();
xh.onload=function()
{
 var txt=this.responseText;
 var iii=txt.indexOf("SOMETEXT"); // put here substring contained in file
 st[NN]=txt.substr(iii,myval); //or st+=txt.substr(iii,myval);

 console.log("done");
}

console.log("go"); NN--; xh.open("GET","http://some.url/bigfile?"+Math.random()); xh.send();

3. Iterate last line some times by any manner (hands, events, timers etc) and take memory snapshot, or even wait up to page fails (how long is depends on file size and your RAM).

3.1. Set myval to values less than 12 to fix the problem. Set again to larger than 12 to continue heap growing.

3.2. Value of NN is for example only, you may set it any positive or even remove array and use concatenation (st+=txt.substr(...))

What is the expected behavior?
Execution without memory leaks with any myval values, if indexOf finds substring.

What went wrong?
When substring is found, memory leak rises if myval > 12. 

Did this work before? N/A 

Chrome version: 65.0.3325.146  Channel: n/a
OS Version: 10.0
Flash Version: 

Tested on:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0

Issue revealed during implementation of some code with large amount of XHR queries in, to find substrings in server responses. To avoid memory leak in production code I now take full substring (which is much longer than 12 bytes) by 12-byte chunks.
 
Labels: Needs-Triage-M65

Comment 2 by ricea@chromium.org, Mar 16 2018

Components: -Blink Blink>MemoryAllocator>GarbageCollection
Interesting. My guess would be that substrings are implemented as references into the longer string, and so keep it alive. Sending to Blink>MemoryAllocator>GarbageCollection component for confirmation.
Cc: vamshi.kommuri@chromium.org
Labels: Triaged-ET Needs-Feedback
@brizala: Could you please share a sample test file/URL which helps us to triage the issue further, as we are not very sure about any site with a big file which avoids CORS issues.

Any further inputs from your end may help us.

Thanks!

Comment 4 by briz...@gmail.com, Mar 20 2018

2vamshi.kommuri:

OK, try it:
1. go to https://ocw.mit.edu/ and open console
2. let set searching word as "twelve" in code above
3. set file parameter as "https://ocw.mit.edu/ans7870/6/6.006/s08/lecturenotes/files/t8.shakespeare.txt" (about 5 Mb)
4. now play few times with iterations, value of myval, and heap snapshoting - so looking at Summary/(string) reveals the number of identical (in this showcase) strings growing if myval > 12.

PS Possibly ricea@ was right (Comment2), it seems your substring implementation hauls an unneeded original string internally.
123.png
123 KB View Download
Project Member

Comment 5 by sheriffbot@chromium.org, Mar 20 2018

Labels: -Needs-Feedback
Thank you for providing more feedback. Adding the requester to the cc list.

For more details visit https://www.chromium.org/issue-tracking/autotriage - Your friendly Sheriffbot

Comment 6 by ricea@chromium.org, Mar 27 2018

Cc: yukishiino@chromium.org
cc +yukishiino who knows something about garbage collection. Can you confirm my guess in #2?
Components: -Blink>MemoryAllocator>GarbageCollection Blink>JavaScript
Owner: adamk@chromium.org
Adam(ricea)'s guess seems correct to me.

https://cs.chromium.org/chromium/src/v8/src/factory.cc?rcl=2943c641a94a3b5e5847f3549af11a8df03cd8cd&l=866
where V8 seems creating a SlicedString that has a reference to the parent string if the substring length is not less than SlicedString::kMinLength (= 13).

Adam(adamk), would you triage this issue?  This seems like a V8 issue to me.

Comment 8 by adamk@chromium.org, Mar 27 2018

Cc: adamk@chromium.org
Components: -Blink>JavaScript Blink>JavaScript>Runtime
Owner: verwa...@chromium.org
Status: Assigned (was: Unconfirmed)
Indeed this is due to V8, though the code in question is not the factory but the CodeStubAssembler in this case:

https://cs.chromium.org/chromium/src/v8/src/code-stub-assembler.cc?rcl=2943c641a94a3b5e5847f3549af11a8df03cd8cd&l=5038

Marking as a V8 Runtime issue and assigning to verwaest@ for further triage, though in some sense this is "working as intended".

Comment 9 by adamk@chromium.org, Mar 28 2018

Cc: jkummerow@chromium.org
Owner: ishell@chromium.org
Re-assigning to ishell for possibly-faster response.
Mergedinto: v8:2869
Status: Duplicate (was: Assigned)
Indeed, sliced strings keep their "parent" alive. This is unfortunate, but difficult to solve.

For the record, this is not at all specific to XHR responses, a repro is as simple as:

var long_lived = (function() {
  var huge_string = (new Array(1000000)).join("x");
  return huge_string.substr(1, 20);
})();

And "huge_string" will stay alive as long as "long_lived" is around.

Sign in to add a comment