Skip to content

Instantly share code, notes, and snippets.

@MaxGraey
Last active November 29, 2018 10:35
Show Gist options
  • Save MaxGraey/3630c0b7ee0ec45411fd1cf0f398696a to your computer and use it in GitHub Desktop.
Save MaxGraey/3630c0b7ee0ec45411fd1cf0f398696a to your computer and use it in GitHub Desktop.
Unicode aware reverse string Benchmarks
'use strict';
// run:
// node --expose-gc reverse-string.js
/*
node v11.3.0, MacBook Late 2013
Bench results:
[Naive reverse string]
memory: 93.91888427734375 MiB
time: 3.484208316 sec
[Unicode-Aware reverse string]
memory: 40.07898712158203 MiB
time: 0.41119796200000003 sec
*/
const symbols = /([\0-\u02FF\u0370-\u1DBF\u1E00-\u20CF\u2100-\uD7FF\uDC00-\uFE1F\uFE30-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF])([\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]+)/g;
const surrogates = /([\uD800-\uDBFF])([\uDC00-\uDFFF])/g;
const fromCharCode = String.fromCharCode;
function reverse(str) {
str = str
.replace(symbols, ($0, $1, $2) => reverse($2) + $1)
.replace(surrogates, '$2$1');
const len = str.length;
const res = new Uint16Array(len);
for (let i = 0; i < len; ++i) {
res[len - i - 1] = str.charCodeAt(i);
}
let chunk = 2048, i = 0, output = '';
while (i < len) {
output += fromCharCode.apply(String, res.subarray(i, i + chunk));
i += chunk;
}
return output;
}
function reverseNaive(s) {
return s.split('').reverse().join('');
}
console.log('naive reverse string1:', reverseNaive('mañana'));
console.log('naive reverse string2:', reverseNaive('foo 𝌆 bar'));
console.log('reverse string1:', reverse('mañana'));
console.log('reverse string2:', reverse('foo 𝌆 bar'));
console.log('');
const base = require('crypto').randomBytes(2e5).toString();
function bench(name, callback) {
global.gc && global.gc();
const m0 = process.memoryUsage().heapUsed;
const t0 = process.hrtime();
const arr = [];
for (let i = 0; i < 100; ++i) {
arr.push(callback(`${i}${base}${i}`));
}
const t1 = process.hrtime(t0);
const m1 = process.memoryUsage().heapUsed;
console.log(`[${name}]`);
console.log(`memory: ${((m1 - m0) / 2 ** 20)} MiB\ntime: ${(t1[0] + t1[1] * 1e-9)} sec\n`);
}
bench('Naive reverse string', str => reverseNaive(str));
bench('Unicode-Aware reverse string', str => reverse(str));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment