如何使用perf_hooks衡量异步操作?

时间:2019-05-22 16:32:13

标签: node.js

以下代码描述了foo方法执行的两个异步操作:

const foo = async () => {
  await new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, Math.random() * 100);
  });

  await new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, 100);
  });
};

Promise.all([
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo()
])

我想测量每个异步操作要花多长时间,然后每个foo执行总共要花多长时间。

我的第一次尝试是:

const { PerformanceObserver, performance } = require('perf_hooks');

const obs = new PerformanceObserver((items) => {
  console.log('performance-observer', items.getEntries());
});

obs.observe({
  entryTypes: ['measure']
});

const foo = async () => {
  performance.mark('A');

  await new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, Math.random() * 100);
  });

  performance.mark('B');

  await new Promise((resolve) => {
    setTimeout(() => {
      resolve();
    }, 100);
  });

  performance.mark('C');

  performance.measure('A to B', 'A', 'B');
  performance.measure('A to C', 'A', 'C');
  performance.measure('B to C', 'B', 'C');

  performance.clearMarks();
};

Promise.all([
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo()
]);

但是,这(按预期)会引发错误:

(node:29277) UnhandledPromiseRejectionWarning: Error [ERR_INVALID_PERFORMANCE_MARK]: The "B" performance mark has not been set
    at Performance.measure (perf_hooks.js:396:13)
    at foo (/Users/gajus/Documents/dev/temp/test.js:30:15)
    at async Promise.all (index 0)

之所以会发生这种情况,是因为PerformanceObserver的实例与各个性能标记之间没有任何关系。

如何使用perf_hooks来衡量异步操作?

1 个答案:

答案 0 :(得分:0)

看起来除了在 resolve 之后进行标记和测量之外别无他法。

const foo = async () => {
  await new Promise((resolve) => {
    performance.mark('A');

    setTimeout(() => {
      resolve();
      performance.mark('B');
      performance.measure('A to B', 'A', 'B');
    }, Math.random() * 100);
  });

  await new Promise((resolve) => {
    performance.mark('C');
    setTimeout(() => {
      resolve();
      performance.mark('D');
      performance.measure('C to D', 'C', 'D');
    }, 100);
  });

  performance.clearMarks();
};

Promise.all([
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
  foo(),
]);