Performance Measurement APIs در Node.js

ماژول node:perf_hooks در Node.js پیاده‌سازی بخشی از W3C Web Performance APIs و همچنین APIهای اختصاصی برای اندازه‌گیری عملکرد در محیط Node.js را فراهم می‌کند. این ماژول ابزارهایی برای اندازه‌گیری زمان با دقت بالا، ثبت رویدادهای عملکرد، و تحلیل چرخهٔ رویدادها ارائه می‌دهد.

High Resolution TimePerformance TimelineUser TimingResource TimingPerformanceObserverperformance.mark / performance.measureeventLoopUtilizationperformance.now / performance.timeOrigin

~6 دقیقه مطالعه • بروزرسانی ۹ دی ۱۴۰۴

1. معرفی


ماژول perf_hooks امکان اندازه‌گیری دقیق عملکرد برنامه‌های Node.js را فراهم می‌کند. مشابه window.performance در مرورگرها، اما با افزونه‌های خاص Node.js.


2. PerformanceObserver


برای مشاهدهٔ رویدادهای عملکرد استفاده می‌شود:


const { PerformanceObserver, performance } = require('node:perf_hooks');
const obs = new PerformanceObserver((items) => {
  console.log(items.getEntries()[0].duration);
});
obs.observe({ type: 'measure' });
performance.measure('Start to Now');

3. متدهای اصلی performance


  • performance.mark(name[, options]): ثبت یک نقطهٔ زمانی (mark).
  • performance.measure(name[, startMark, endMark]): اندازه‌گیری مدت زمان بین دو mark.
  • performance.clearMarks([name]): پاک کردن markها.
  • performance.clearMeasures([name]): پاک کردن measureها.
  • performance.clearResourceTimings([name]): پاک کردن resource timings.

4. مدیریت چرخهٔ رویداد


  • performance.eventLoopUtilization(): اندازه‌گیری میزان استفاده از چرخهٔ رویداد (idle, active, utilization).

5. دریافت داده‌ها


  • performance.getEntries(): لیست همهٔ PerformanceEntryها.
  • performance.getEntriesByName(name[, type]): فیلتر بر اساس نام.
  • performance.getEntriesByType(type): فیلتر بر اساس نوع.

6. زمان با دقت بالا


  • performance.now(): زمان جاری با دقت میلی‌ثانیه از شروع پردازش Node.js.
  • performance.timeOrigin: زمان آغاز پردازش Node.js به‌صورت timestamp.

7. ویژگی‌های اختصاصی Node.js


  • performance.nodeTiming: متریک‌های مربوط به نقاط کلیدی اجرای Node.js.
  • performance.markResourceTiming(): ثبت زمان‌بندی منابع.
  • performance.timerify(fn[, options]): اندازه‌گیری مدت زمان اجرای یک تابع.
  • performance.setResourceTimingBufferSize(maxSize): تنظیم اندازهٔ بافر resource timings.

نتیجه‌گیری


ماژول perf_hooks در Node.js ابزاری قدرتمند برای تحلیل عملکرد برنامه‌هاست. با استفاده از متدهای آن می‌توان نقاط کلیدی را علامت‌گذاری کرد، مدت زمان اجرای بخش‌های مختلف را اندازه گرفت، و چرخهٔ رویدادها را بررسی نمود. این قابلیت‌ها برای بهینه‌سازی و پایش برنامه‌های بزرگ و پیچیده ضروری هستند.


1. performance.toJSON()


این متد یک نمایش JSON از شیء performance بازمی‌گرداند. مشابه window.performance.toJSON در مرورگرها.


2. رویداد resourcetimingbufferfull


هنگامی که بافر resource timing پر شود، این رویداد منتشر می‌شود. می‌توان با performance.setResourceTimingBufferSize() اندازهٔ بافر را تغییر داد یا با performance.clearResourceTimings() آن را پاک کرد.


3. کلاس PerformanceEntry


کلاس پایه برای همهٔ ورودی‌های عملکرد. ویژگی‌ها:


  • duration: مدت زمان سپری‌شده.
  • entryType: نوع ورودی (dns, function, gc, http, http2, mark, measure, net, node, resource).
  • name: نام ورودی.
  • startTime: زمان شروع با دقت بالا.

4. کلاس PerformanceMark


زیرکلاسی از PerformanceEntry که با performance.mark() ایجاد می‌شود. ویژگی:


  • detail: اطلاعات اضافی هنگام ایجاد mark.

5. کلاس PerformanceMeasure


زیرکلاسی از PerformanceEntry که با performance.measure() ایجاد می‌شود. ویژگی:


  • detail: اطلاعات اضافی هنگام ایجاد measure.

6. کلاس PerformanceNodeEntry


زیرکلاسی اختصاصی Node.js برای داده‌های زمان‌بندی داخلی. ویژگی‌ها:


  • detail: اطلاعات اضافی بسته به نوع entry.
  • flags و kind: (منسوخ) برای عملیات Garbage Collection.

7. جزئیات Garbage Collection (gc)


هنگام entryType برابر با gc، ویژگی detail شامل:


  • kind: نوع GC (major, minor, incremental, weakcb).
  • flags: وضعیت GC (forced, retained, idle schedule و غیره).

8. جزئیات HTTP


هنگام entryType برابر با http، ویژگی detail شامل:


  • req: شامل method, url, headers.
  • res: شامل statusCode, statusMessage, headers.

این قابلیت برای عیب‌یابی است و نباید در محیط production فعال بماند.


9. جزئیات HTTP/2


هنگام entryType برابر با http2، ویژگی detail شامل:


  • Http2Stream: شامل bytesRead, bytesWritten, id, timeToFirstByte, timeToFirstHeader.
  • Http2Session: شامل framesSent, framesReceived, maxConcurrentStreams, pingRTT, streamCount.

1. جزئیات DNS ('dns')


هنگامیکه performanceEntry.type برابر با dns باشد، ویژگی detail شامل اطلاعات زیر است:


  • lookup: شامل hostname، family، hints، verbatim، addresses.
  • lookupService: شامل host، port، hostname، service.
  • queryxxx / getHostByAddr: شامل host، ttl، result.

2. کلاس PerformanceNodeTiming


زیرکلاسی از PerformanceEntry که زمان‌بندی داخلی Node.js را نشان می‌دهد:


  • bootstrapComplete: زمان پایان bootstrapping.
  • environment: زمان مقداردهی محیط.
  • idleTime: زمان بیکاری event loop.
  • loopStart / loopExit: زمان شروع و پایان event loop.
  • nodeStart: زمان آغاز پردازش Node.js.
  • uvMetricsInfo: شامل loopCount، events، eventsWaiting.
  • v8Start: زمان آغاز پلتفرم V8.

3. کلاس PerformanceResourceTiming


برای داده‌های دقیق زمان‌بندی شبکه هنگام بارگذاری منابع:


  • workerStart: زمان قبل از dispatch درخواست.
  • redirectStart / redirectEnd: زمان آغاز و پایان redirect.
  • fetchStart: زمان آغاز fetch.
  • domainLookupStart / domainLookupEnd: زمان آغاز و پایان lookup دامنه.
  • connectStart / connectEnd: زمان آغاز و پایان اتصال.
  • secureConnectionStart: زمان آغاز handshake امنیتی.
  • requestStart / responseEnd: زمان آغاز درخواست و پایان پاسخ.
  • transferSize / encodedBodySize / decodedBodySize: اندازه‌های مختلف دادهٔ منتقل‌شده.

4. کلاس PerformanceObserver


برای مشاهدهٔ رویدادهای جدید در Performance Timeline استفاده می‌شود:


  • PerformanceObserver.supportedEntryTypes: لیست انواع پشتیبانی‌شده.
  • observe(options): ثبت observer برای انواع خاص.
  • disconnect(): قطع ارتباط observer.
  • takeRecords(): دریافت لیست ورودی‌های ذخیره‌شده.

5. کلاس PerformanceObserverEntryList


برای دسترسی به ورودی‌های PerformanceEntry که به observer داده می‌شوند:


  • getEntries(): لیست همهٔ ورودی‌ها.
  • getEntriesByName(name[, type]): فیلتر بر اساس نام و نوع.

نتیجه‌گیری


جزئیات DNS، کلاس‌های PerformanceNodeTiming و PerformanceResourceTiming، و ابزارهای PerformanceObserver در Node.js امکان تحلیل دقیق عملکرد و منابع را فراهم می‌کنند. این قابلیت‌ها برای پایش چرخهٔ رویداد، بررسی بارگذاری منابع، و عیب‌یابی مشکلات شبکه‌ای در برنامه‌های بزرگ ضروری هستند.


1. performanceObserverEntryList.getEntriesByType(type)


لیستی از PerformanceEntryها را بر اساس نوع بازمی‌گرداند:


const { performance, PerformanceObserver } = require('node:perf_hooks');
const obs = new PerformanceObserver((list, observer) => {
  console.log(list.getEntriesByType('mark'));
  performance.clearMarks();
  performance.clearMeasures();
  observer.disconnect();
});
obs.observe({ type: 'mark' });
performance.mark('test');
performance.mark('meow');

2. perf_hooks.createHistogram([options])


یک RecordableHistogram برای اندازه‌گیری مدت زمان‌ها ایجاد می‌کند:


  • lowest: کمترین مقدار قابل تشخیص.
  • highest: بیشترین مقدار قابل ثبت.
  • figures: تعداد ارقام دقت (۱ تا ۵).

3. perf_hooks.eventLoopUtilization()


مقادیر idle، active و utilization چرخهٔ رویداد را بازمی‌گرداند. امکان محاسبهٔ دلتا بین فراخوانی‌ها مشابه process.hrtime() وجود دارد.


const { eventLoopUtilization } = require('node:perf_hooks');
setImmediate(() => {
  const elu = eventLoopUtilization();
  console.log(eventLoopUtilization(elu).utilization);
});

4. perf_hooks.monitorEventLoopDelay([options])


یک IntervalHistogram برای نمونه‌برداری از تأخیرهای چرخهٔ رویداد ایجاد می‌کند:


  • resolution: نرخ نمونه‌برداری بر حسب میلی‌ثانیه (پیش‌فرض: ۱۰).

const { monitorEventLoopDelay } = require('node:perf_hooks');
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
// ... عملیات ...
h.disable();
console.log(h.mean, h.max, h.percentile(99));

5. perf_hooks.timerify(fn[, options])


یک تابع را برای اندازه‌گیری زمان اجرا wrap می‌کند. نیاز به PerformanceObserver دارد که به 'function' مشترک شده باشد:


const { timerify, PerformanceObserver } = require('node:perf_hooks');
function hello() { console.log('world'); }
const wrapped = timerify(hello);
const obs = new PerformanceObserver((list) => {
  console.log(list.getEntries()[0].duration);
});
obs.observe({ entryTypes: ['function'] });
wrapped();

6. کلاس‌های Histogram


  • Histogram: کلاس پایه با min، max، mean، stddev، percentiles.
  • IntervalHistogram: زیرکلاس Histogram که به‌طور دوره‌ای به‌روزرسانی می‌شود.
  • RecordableHistogram: زیرکلاس Histogram با قابلیت record(), recordDelta(), و add().

7. نمونه‌های کاربردی


  • اندازه‌گیری مدت زمان عملیات async با performance.mark و measure.
  • ردگیری زمان بارگذاری وابستگی‌ها با timerify(require).
  • پایش زمان رفت‌وبرگشت HTTP با ورودی‌های 'http'.
  • اندازه‌گیری زمان اتصال TCP با ورودی‌های 'net'.
  • ردگیری مدت زمان lookup در DNS با ورودی‌های 'dns'.

نتیجه‌گیری


APIهای پیشرفته در perf_hooks—شامل هیستوگرام‌ها، پایش چرخهٔ رویداد، و timerify—ابزارهای دقیقی برای تحلیل عملکرد فراهم می‌کنند. با ترکیب این قابلیت‌ها با PerformanceObserver، می‌توان برنامه‌های Node.js را با دقت بالا پروفایل و بهینه‌سازی کرد.


10. جزئیات Timerify (function)


هنگام entryType برابر با function، ویژگی detail شامل آرایه‌ای از آرگومان‌های ورودی تابع زمان‌سنجی‌شده است.


11. جزئیات Net


هنگام entryType برابر با net، ویژگی detail شامل:


  • connect: شامل host و port.

نتیجه‌گیری


کلاس‌های PerformanceEntry و زیرکلاس‌های آن در Node.js ابزارهای قدرتمندی برای تحلیل عملکرد و عیب‌یابی فراهم می‌کنند. با استفاده از این داده‌ها می‌توان زمان‌بندی دقیق عملیات داخلی، درخواست‌های HTTP/HTTP2، و چرخهٔ Garbage Collection را بررسی کرد و برنامه‌ها را بهینه‌سازی نمود.


نوشته و پژوهش شده توسط دکتر شاهین صیامی