denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
97.5k stars 5.37k forks source link

Significant perf gains possible on simple "create object and serialize" task? #21008

Open josephrocca opened 1 year ago

josephrocca commented 1 year ago

While investigating a problem on one of my production servers (where, in case you're curious, an operation wasn't completing in time after a SIGINT, resulting in a SIGKILL by pm2), I eventually ended up with this micro-benchmark:

let t = performance.now();

let obj = {};
for(let i = 0; i < 5000000; i++) {
  obj[i] = Math.random();
}

console.log("time to make obj:", performance.now() - t);

t = performance.now();

let str = "";
for(let key in obj) {
  str += `${key}: ${obj[key]}\n`;
}

console.log("time to make str:", performance.now() - t);
bun main.js
deno run main.js

Bun is ~10x faster at making obj, and ~1.5x faster at making str. If I change Math.random() to "aaaaaaaaaaaaaa", then Bun is only ~5x faster at making obj.

I also tried "aaaaaaaaaaaaaa😊" in case it was somehow related to (lack of) Latin-1 optimizations, but that didn't affect the scores.

In Chrome (I only tested v118), making obj is ~10x slower, but making str is about the same speed as in Bun, weirdly.

This isn't a huge deal for me (unlike #20409 and #20428 and especially #20355), so I don't want to risk drawing dev hours away from more important things, but it is an actual issue I had in production, so I figured it'd be a shame not to share it.

Please close if this is better filed on crbug.

mmastrac commented 1 year ago

Interesting. I would suspect V8 to be honest, but is there a reason you aren't using arrays and join?

josephrocca commented 1 year ago

I'm not sure why (just V8 optimization-fu, I guess?), but if this is what you meant:

let chunks = [];
for(let key in obj) {
  chunks.push(`${key}: ${obj[key]}`);
}
let str = chunks.join("\n");

that does indeed get significantly closer to matching Bun performance. For Bun, the previous "string append" approach is about 10% faster than the above array version.

Fastest Bun:

time to make obj: 73.572666
time to make str: 4352.123359 ("string append" approach)

Fastest Deno:

time to make obj: 1102
time to make str: 5240 ("array join" approach)