Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force JavaScript to deep copy a string?

I have some javascript code which looks like this:

var myClass = {   ids: {}   myFunc: function(huge_string) {      var id = huge_string.substr(0,2);      ids[id] = true;   } } 

Later the function gets called with some large strings (100 MB+). I only want to save a short id which I find in each string. However, the Google Chrome's substring function (actually regex in my code) only returns a "sliced string" object, which references the original. So after a series of calls to myFunc, my chrome tab runs out of memory because the temporary huge_string objects are not able to be garbage collected.

How can I make a copy of the string id so that a reference to the huge_string is not maintained, and the huge_string can be garbage collected?

enter image description here

like image 925
AffluentOwl Avatar asked Jul 29 '15 23:07

AffluentOwl


People also ask

How do you make a deep copy in JavaScript?

Copy an Object With Object. assign() was the most popular way to deep copy an object. Object. assign() will copy everything into the new object, including any functions. Mutating the copied object also doesn't affect the original object.

How do I duplicate a string in JavaScript?

repeat() is an inbuilt function in JavaScript which is used to build a new string containing a specified number of copies of the string on which this function has been called. Syntax: string. repeat(count);

Does JavaScript shallow copy?

Like most other programming languages JavaScript allows supports the concept of deep copy and shallow copy. Shallow Copy: When a reference variable is copied into a new reference variable using the assignment operator, a shallow copy of the referenced object is created.


1 Answers

JavaScript's implementation of ECMAScript can vary from browser to browser, however for Chrome, many string operations (substr, slice, regex, etc.) simply retain references to the original string rather than making copies of the string. This is a known issue in Chrome (Bug #2869). To force a copy of the string, the following code works:

var string_copy = (' ' + original_string).slice(1); 

This code works by appending a space to the front of the string. This concatenation results in a string copy in Chrome's implementation. Then the substring after the space can be referenced.

This problem with the solution has been recreated here: http://jsfiddle.net/ouvv4kbs/1/

WARNING: takes a long time to load, open Chrome debug console to see a progress printout.

// We would expect this program to use ~1 MB of memory, however taking // a Heap Snapshot will show that this program uses ~100 MB of memory. // If the processed data size is increased to ~1 GB, the Chrome tab // will crash due to running out of memory.  function randomString(length) {   var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';   var result = '';   for (var i = 0; i < length; i++) {     result +=         alphabet[Math.round(Math.random() * (alphabet.length - 1))];   }   return result; };  var substrings = []; var extractSubstring = function(huge_string) {   var substring = huge_string.substr(0, 100 * 1000 /* 100 KB */);   // Uncommenting this line will force a copy of the string and allow   // the unused memory to be garbage collected   // substring = (' ' + substring).slice(1);   substrings.push(substring); };  // Process 100 MB of data, but only keep 1 MB. for (var i =  0; i < 10; i++) {   console.log(10 * (i + 1) + 'MB processed');   var huge_string = randomString(10 * 1000 * 1000 /* 10 MB */);   extractSubstring(huge_string); }  // Do something which will keep a reference to substrings around and // prevent it from being garbage collected. setInterval(function() {   var i = Math.round(Math.random() * (substrings.length - 1));   document.body.innerHTML = substrings[i].substr(0, 10); }, 2000); 

enter image description here

like image 123
AffluentOwl Avatar answered Sep 25 '22 18:09

AffluentOwl