0

I'm making a hex dumper in JavaScript that will analyze the byte data of a file provided by the user. In order to properly display the data preview of the file, I'm escaping html characters using the methods from the top rated answer of this question.

function htmlEncode(value) { return $("<div/>").text(value).html(); }
function htmlDecode(value) { return $("<div/>").html(value).text(); }

I'm not asking for suggestions of how to best encode and decode html characters. What I am curious about is whether or not calling these functions hundreds of thousands of times in rapid succession is creating a metric butt-ton of DOM elements that will slow down the utility over time.

I've noticed that running my dumper on a small file (35 bytes), which thankfully runs almost instantaneously, takes much longer after I've run my dumper on a larger file (132,832 bytes) in the same session. The encode function is essentially run once for each byte.

I know JavaScript has a garbage collector, and these elements aren't tied to anything so I would assume they would get cleaned up after they're done being used, but I don't know the details or inner workings of the collector so I don't want to make any assumptions as to how quickly it will take care of the problem.

Community
  • 1
  • 1
Taylor Lopez
  • 813
  • 1
  • 8
  • 28
  • Yes, you're creating a metric butt-ton of elements. However, none of them are being inserted into the DOM so they should immediately be collected on the next garbage collection cycle. Possibly faster depending on how optimized the engine is. – Mike Cluck Jun 10 '16 at 16:27
  • @Azamantes By faster, I mean without waiting for the garbage collector cycle. It's possible to clean them as the stack is popped. – Mike Cluck Jun 10 '16 at 16:29
  • 1
    You can try to reuse always the same $("
    ") as you are actually overriding its context all the time
    – juvian Jun 10 '16 at 16:30
  • @Mike I'm going to read about it. Thanks for pointing that out. – Azamantes Jun 10 '16 at 16:34

1 Answers1

0

Theoretically it's possible that you're generating a lot of memory because you are creating numerous new elements. However, since they are not being added to the DOM, they should be cleaned up either on the next garbage collector cycle or while the stack is being popped (depends on how optimized the engine is).

But, as @juvian pointed out, you can get around this by having one dedicated element that you use for this operation. Not only will it ensure you aren't filling up your memory but it will also be faster since jQuery won't have to repeatedly process the <div/> string, create an element, generate a jQuery object, etc.

Here's my not-completely-scientifically-sound-but-definitely-good-enough-to-get-the-idea proof:

function now() {
  if (typeof performance !== 'undefined') {
    now = performance.now.bind(performance);
    return performance.now();
  } else {
    now = Date.now.bind(Date);
    return Date.now();
  }
}
// Load the best available means of measuring the current time
now();

// Generate a whole bunch of characters
var data = [];
var totalNumberOfCharacters = 132832;
for (var i = 0; i < totalNumberOfCharacters; i++) {
  data.push(String.fromCharCode((i % 26) + 65));
}

// Basic encode function
function htmlEncode(value) {
  return $("<div/>").text(value).html();
}

// Cache a single <div> to improve performance
var $div = $('<div/>');
function cachedHtmlEncode(value) {
  return $div.text(value).html();
}

// Encode using the unoptimized approach
var start = now();
var unoptimized = '';
for (var i = 0; i < totalNumberOfCharacters; i++) {
  unoptimized += htmlEncode(data[i]);
}
var end = now();
console.log('unoptimized', end - start);
document.querySelector('pre').innerText = unoptimized;

// Encode using the optimized approach
start = now();
var optimized = '';
for (var i = 0; i < totalNumberOfCharacters; i++) {
  optimized += cachedHtmlEncode(data[i]);
}
end = now();
console.log('optimized', end - start);
document.querySelector('pre').innerText = optimized;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre></pre>
Mike Cluck
  • 31,869
  • 13
  • 80
  • 91