hexo-util icon indicating copy to clipboard operation
hexo-util copied to clipboard

perf(escapeHTML): use multiple replace

Open SukkaW opened this issue 5 years ago • 4 comments

Benchmark: https://runkit.com/sukkaw/5e3003ffe7e84c0013f6210d

const Benchmark = require('benchmark');
const Suite = new Benchmark.Suite;
const html = `<p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p>`;
const htmlEntityMap = {
  '&': '&amp;',
  '<': '&lt;',
  '>': '&gt;',
  '"': '&quot;',
  '\'': '&#39;',
  '`': '&#96;',
  '/': '&#x2F;',
  '=': '&#x3D;'
};

Suite.add('Map replacement', () => {
  html.replace(/[&<>"'`/=]/g, a => htmlEntityMap[a]);
}).add('Multiple replace', () => {
  html.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/\\/g, '&#39;').replace(/`/g, '&#96;').replace(/\//g, '&#x2F').replace(/=/g, '&#x3D');
}).on('cycle', function(event) {
  console.info(String(event.target));
}).run();

On my local computer, Multiple replace is the slower one under Node.js 10 but it is the faster one under Node.js 12 & 13:

image

SukkaW avatar Jan 28 '20 10:01 SukkaW

Coverage Status

Coverage decreased (-0.01%) to 96.979% when pulling 087af7138f95f00b526c5be77bf45a0459b66d64 on SukkaW:perf-escape-unescape into 4e7c24e2174436cca57a0fcd9cc2c68b42e2607a on hexojs:master.

coveralls avatar Jan 28 '20 10:01 coveralls

Coverage Status

Coverage decreased (-0.01%) to 96.979% when pulling 087af7138f95f00b526c5be77bf45a0459b66d64 on SukkaW:perf-escape-unescape into 4e7c24e2174436cca57a0fcd9cc2c68b42e2607a on hexojs:master.

coveralls avatar Jan 28 '20 10:01 coveralls

I modified the source text to include all special characters.

const html = `<p class="foo">Hello "world&".</p><p class="foo">Hello "world\"".</p><p class="foo">Hello "world\`".</p><p class="foo">Hello "world=".</p><p class="foo">Hello "world\\".</p><p class="foo">Hello "world&".</p><p class="foo">Hello "world\"".</p><p class="foo">Hello "world\`".</p><p class="foo">Hello "world=".</p><p class="foo">Hello "world\\".</p><p class="foo">Hello "world&".</p><p class="foo">Hello "world\"".</p><p class="foo">Hello "world\`".</p><p class="foo">Hello "world=".</p><p class="foo">Hello "world\\".</p><p class="foo">Hello "world&".</p><p class="foo">Hello "world\"".</p><p class="foo">Hello "world\`".</p><p class="foo">Hello "world=".</p><p class="foo">Hello "world\\".</p><p class="foo">Hello "world&".</p><p class="foo">Hello "world\"".</p><p class="foo">Hello "world\`".</p><p class="foo">Hello "world=".</p><p class="foo">Hello "world\\".</p><p class="foo">Hello "world".</p><p class="foo">Hello "world".</p>`;

The result of benchmark with Node v12 is reversal. Multiple replace is slower.

SS20200130b0 perf_escapeHTML_v12

The result of benchmark with Node v13 is same as SukkaW's report. Multiple replace is faster.

SS20200130a0 perf_escapeHTML_v13

It is certain that my sample source text is unusual HTML. I only show that this patch is not all-around. Because this patch sacrifices readability, the profit seems too little.

seaoak avatar Jan 30 '20 08:01 seaoak

More performance benchmark needs to be done before we merge this.

SukkaW avatar Jan 16 '22 04:01 SukkaW