Deno 的性能

ymo*_*291 5 deno

我一直在用Deno一点。出于某种原因,我决定比较 Deno 和 Node 之间的性能。Deno 的性能现在似乎是一个热门话题,但人们几乎总是在讨论 HTTP 吞吐量。我感兴趣的是看看 Deno 在基本 JS 功能方面与 Node 相比如何for loops,例如, Array.map, JSON.stringify, ...

我正在比较 Deno 1.5.2 (v8 8.7.220.3) 和 Node 15.2.0 (v8 8.6.395.17)。由于 JS 在这两种情况下都由非常相似的 v8 版本解释,因此我希望代码在两种情况下都能以同样快的速度运行。

我准备了一个.js文件,在两个运行时上运行 10 个函数 100 万次。我过去常常Date.now()以毫秒为单位测量持续时间,因为它在两个运行时之间都很常见。

const list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
const obj1 = {foo: 1};
const obj2 = {bar: 1};
const json = JSON.stringify(obj1);

// Declare the performance tool (different between Node and Deno)
let perf;
try {
  // Use perf_hooks in Node
  perf = require("perf_hooks").performance;
} catch {
  // Use performance in Deno
  perf = performance
}

// Declare the test functions
function mapFn() {return list.map(num => num*10);}
function reduceFn() {return list.reduce((a, b) => a+b);}
function forEachFn() {return list.forEach(num => num*10);}
function sliceFn() {return list.slice(0, 5);}
function forFn() {for (let i = 0; i < list.length; i++) {list[i]*10};}
function objectAssignFn() {return Object.assign({}, obj1, obj2)};
function jsonStringifyFn() {return JSON.stringify(obj1)};
function jsonParseFn() {return JSON.parse(json)};
function markFn() {perf.mark()};
function nowFn() {perf.now()};

// Loop through each test function and measure the time it takes
// to execute 1 million iterations.
[
  mapFn,
  reduceFn,
  forEachFn,
  sliceFn,
  forFn,
  objectAssignFn,
  jsonStringifyFn,
  jsonParseFn,
  markFn,
  nowFn,
]
  .forEach(fn => {
    let start = Date.now();
    for (let i = 0; i < 1000000; i++) {
      fn();
    }
    let end = Date.now();
    console.log(`${fn.name} - Time elapsed: ${end-start} ms`);
  });
Run Code Online (Sandbox Code Playgroud)

结果如下:

结果 - Deno

// deno run app.js 
mapFn - Time elapsed: 171 ms
reduceFn - Time elapsed: 26 ms
forEachFn - Time elapsed: 17 ms
sliceFn - Time elapsed: 54 ms
forFn - Time elapsed: 17 ms
objectAssignFn - Time elapsed: 95 ms
jsonStringify - Time elapsed: 287 ms
jsonParse - Time elapsed: 472 ms
markFn - Time elapsed: 11905 ms
nowFn - Time elapsed: 10988 ms
Run Code Online (Sandbox Code Playgroud)

结果 - 节点

// node app.js
mapFn - Time elapsed: 64 ms
reduceFn - Time elapsed: 27 ms
forEachFn - Time elapsed: 17 ms
sliceFn - Time elapsed: 76 ms
forFn - Time elapsed: 17 ms
objectAssignFn - Time elapsed: 116 ms
jsonStringify - Time elapsed: 283 ms
jsonParse - Time elapsed: 400 ms
markFn - Time elapsed: 2459 ms
nowFn - Time elapsed: 95 ms
Run Code Online (Sandbox Code Playgroud)

两种运行时都给出了非常相似的结果,+/- 20%。然而,3个结果相当令人惊讶:

  • Array.mapDeno中几乎慢了 3 倍。Array.map因为它是在 V8 中构建的,所以我希望有非常相似的性能。为什么如此大的差别时Array.forEach,并Array.reduce在运行时都以类似的方式进行?
  • Deno 中的performance.now()大约是。在 Deno 中慢 110 倍。我知道性能类主要是为了对我们的代码进行基准测试,所以它怎么会这么慢?它仍然被视为不稳定的功能吗?
  • Deno 中的performance.mark()大约是。在 Deno 中慢 5 倍。为什么会这样?

谢谢!