الواجهات البرمجية لتوقيت الأداء (Performance Timing API)
الاستقرار: 1- تجريبي.
تقدم الواجهة البرمجية لتوقيت الأداء تطبيقًا لمواصفات W3C Performance Timeline. الغرض من الواجهة البرمجية (API) هو دعم مجموعة من مقاييس الأداء عالية الدقة. والتي هي نفس واجهات الأداء المُطبّقة في متصفحات الويب الحديثة.
const { PerformanceObserver, performance } = require('perf_hooks');
const obs = new PerformanceObserver((items) => {
console.log(items.getEntries()[0].duration);
performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('A');
doSomeLongRunningProcess(() => {
performance.mark('B');
performance.measure('A to B', 'A', 'B');
});
الصنف: Performance
أُضيف في الإصدار: 8.5.0.
performance.clearMarks([name])
أُضيفت في الإصدار: 8.5.0
name
<string>
إذا لم يكن المعامل name
مُزودًا، فستُمسَح كل كائنات PerformanceMark
من الجدول الزمني للأداء. أما إذا كانت قيمة name
مزوّدة، فستُمسح العلامة المسماة فقط.
performance.mark([name])
أُضيفت في الإصدار: 8.5.0.
name
<string>
تُنشِئ مُدخل PerformanceMark
جديد في الجدول الزمني للأداء .الصنف PerformanceMark
هو صنف فرعي من PerformanceEntry
وفيه تكون قيمة performanceEntry.entryType
دائمًا 'mark'
( مُعلّمًا). وقيمة performanceEntry.duration
دائمًا 0
. تُستخدم علامات الأداء لتعليم لحظات محددة مهمة في الجدول الزمني للأداء.
(performance.measure(name, startMark, endMark
أُضيفت في الإصدار: 8.5.0.
تُنشِئ مُدخل PerformanceMeasure
جديد في الجدول الزمني للأداء. الصنف PerformanceMeasure
هو صنف فرعي من الصنف PerformanceEntry
فيه الخاصية performanceEntry.entryType
ذات قيمة 'measure'
(قياس) دائمًا، والخاصية performanceEntry.duration
خاصته تقيس عدد الملي ثانية المنقضي منذ startMark
و endMark
.
قد يُعرِّف الوسيط startMark
أي PerformanceMark
موجودة في الجدول الزمني للأداء، أو قد يعرّف أي من خاصيات البصمة الزمنية (timestamp) المقدمة من قبل الصنف PerformanceNodeTiming
. إذا كانت قيمة startMark
المُسمّاة غير موجودة، حينذاك تُهيأ قيمة المعامل startMark
وتُضبَط إلى timeOrigin افتراضيًا.
يجب أن يُعرِّف الوسيط endMark
أي PerformanceMark
موجودة في الجدول الزمني للأداء، أو أي من خاصيات البصمة الزمنية (timestamp) المقدمة من خلال الصنف PerformanceNodeTiming
. إذا كان العامل endMark
المسمّى غير موجود، فسوف يُرمى خطأ.
performance.nodeTiming
أُضيفت في الإصدار: 8.5.0.
- <PerformanceNodeTiming>
- نسخة من الصنف
PerformanceNodeTiming
والتي تقدم مقاييس أداء لمراحل تشغيل Node.js محددة.
performance.now()
أُضيفت في الإصدار: 8.5.0.
- القيمة المعادة :<number>
تعيد البصمة الزمنية الحالية عالية الدقة بالميلي ثانية، حيث تمثل القيمة 0 بداية عملية node
الحالية.
performance.timeOrigin
أُضيفت في الإصدار: 8.5.0.
تحدد الخاصية timeOrigin بصمة زمنية عالية الدقة بالميلي ثانية والتي بدأت فيها عملية node
الحالية، مقاسة بتوقيت يونكس.
performance.timerify(fn)
أُضيفت في الإصدار: 8.5.0.
fn
<Function>
تُغلّف الدالة بدالة جديدة والتي تقيس زمن التشغيل للدالة المُغلّفة. يجب أن تكون قيمة PerformanceObserver
مشترِكة ً(subscribed) بنوع الحدث 'function'
من أجل إمكانية الوصول لتفاصيل الزمن.
const {
performance,
PerformanceObserver
} = require('perf_hooks');
function someFunction() {
console.log('hello world');
}
const wrapped = performance.timerify(someFunction);
const obs = new PerformanceObserver((list) => {
console.log(list.getEntries()[0].duration);
obs.disconnect();
});
obs.observe({ entryTypes: ['function'] });
// سوف يُنشأ مُدخل الجدول الزمني للأداء
wrapped();
الصنف PerformanceEntry
أُضيف في الإصدار: 8.5.0.
performanceEntry.duration
أُضيفت في الإصدار: 8.5.0.
العدد الكلي بالميلي ثانية المنقضي من أجل هذا المُدخل. لن تكون هذه القيمة ذات معنى من أجل جميع أنواع مدخلات الأداء.
performanceEntry.name
أُضيفت في الإصدار: 8.5.0.
اسم مُدخل الأداء.
performanceEntry.startTime
أُضيفت في الإصدار: 8.5.0.
البصمة الزمنية عالية الدقة بالميلي ثانية التي تُشير إلى زمن البداية لمُدخل الأداء.
performanceEntry.entryType
أُضيفت في الإصدار: 8.5.0.
نوع مُدخل الأداء، حاليًا قد يكون إما 'node'
أو 'mark'
أو'measure'
أو 'gc'
أو'function'
أو 'http2'
.
performanceEntry.kind
أُضيفت في الإصدار: 8.5.0.
عندما تكون قيمة الخاصية performanceEntry.entryType
مساويةً إلى 'gc'
، تُعرِّف الخاصية performance.kind
نوع عملية جمع القمامة (تنظيف الذاكرة) التي حصلت.
يمكن أن تكون القيمة واحدةً مما يلي:
perf_hooks.constants.NODE_PERFORMANCE_GC_MAJOR
perf_hooks.constants.NODE_PERFORMANCE_GC_MINOR
perf_hooks.constants.NODE_PERFORMANCE_GC_INCREMENTAL
perf_hooks.constants.NODE_PERFORMANCE_GC_WEAKCB
الصنف PerformanceNodeTiming extends PerformanceEntry
أُضيف في الإصدار: 8.5.0.
يقدم تفاصيل التوقيت لمنصة Node.js نفسها.
performanceNodeTiming.bootstrapComplete
أُضيفت في الإصدار: 8.5.0.
البصمة الزمنية عالية الدقة بالميلي ثانية والتي أكملت فيها عملية Node.js تمهيد التشغيل. إذا لم ينته تمهيد التشغيل بعد، فستأخد الخاصية القيمة -1.
performanceNodeTiming.loopExit
أُضيفت في الإصدار: 8.5.0.
بصمة زمنية عالية الدقة بالميلي ثانية والتي انتهت عندها حلقة أحداث Node.js. إذا لم تنتهِ حلقة الأحداث بعد، فستأخذ الخاصية القيمة -1. يمكن فقط أن تأخذ قيمةً لا تساوي -1 في معالج الحدث 'exit'.
performanceNodeTiming.loopStart
أُضيفت في الإصدار: 8.5.0.
البصمة الزمنية عالية الدقة بالميلي ثانية والتي بدأت عندها حلقة أحداث Node.js. إذا لم تبدأ حلقة الأحداث بعد، (على سبيل المثال، في اللحظة الأولى للسكربت الرئيسي)، فستأخذ الخاصية القيمة -1.
performanceNodeTiming.nodeStart
أُضيفت في الإصدار: 8.5.0.
البصمة الزمنية عالية الدقة بالميلي ثانية والذي هُيئت فيها عملية Node.js.
performanceNodeTiming.v8Start
أُضيفت في الإصدار: 8.5.0.
البصمة الزمنية عالية الدقة بالميلي ثانية والتي هُيئت فيها منصة V8.
الصنف: PerformanceObserver
new PerformanceObserver(callback)
أُضيف في الإصدار:8.5.0
callback
<Function>list
<PerformanceObserverEntryList>observer
<PerformanceObserver>
تقدم كائنات PerformanceObserver
إشعارات عندما تُضاف نسخة PerformanceEntry
جديدة إلى الجدول الزمني للأداء.
const {
performance,
PerformanceObserver
} = require('perf_hooks');
const obs = new PerformanceObserver((list, observer) => {
console.log(list.getEntries());
observer.disconnect();
});
obs.observe({ entryTypes: ['mark'], buffered: true });
performance.mark('test');
بسبب أن نُسخ PerformanceObserver
تقدم عبء أداء إضافي خاص بها، لا ينبغي أن تُترك النسخ مشتركةً في الإشعارات لأجل غير مُسمى. ينبغي على المستخدم قطع اتصال المراقِبات(observers) حالما لا توجد حاجة إليها.
تستدعى دالة رد النداء callback عندما تُبلَّغ PerformanceObserver
عن نُسخ PerformanceEntry
جديدة. تستقبل دالة رد النداء (callback) نسخة PerformanceObserverEntryList
ومرجعًا إلى PerformanceObserver
.
performanceObserver.disconnect()
أُضيفت في الإصدار:8.5.0.
تفصل اتصال نسخة PerformanceObserver
عن كل الإشعارات.
performanceObserver.observe(options)
أُضيفت في الإصدار: 8.5.0.
options
<Object>entryTypes
<string[]> مصفوفة من السلاسل النصية مُعرِّفة لأنواع نُسخPerformanceEntry
التي يهتم بها المراقب. إذا لم تكن قيمة هذا المعامل موجودةً فسوف يُرمى خطأ.buffered
<boolean> إذا كانت true، سوف تستدعى دالة رد النداء callback للإشعارات باستخدامsetImmediate()
وستُخزَّن محليًا العديد من إشعارات نُسخPerformanceEntry
. إذا كانتfalse
، فسوف تكون الإشعارات آنية ومتزامنة. القيمة الافتراضية:false
.
تُؤدي هذه الدالة إلى جعل نسخة الصنف PerformanceObserver
مشتركةً بإشعارات النسخ الجديدة من PerformanceEntry
المُعرَّفة بواسطة الخاصية options.entryTypes
.
عندما تكون قيمة الخاصية options.buffered
هي false، فستُستدعى دالة رد النداء callback
مرةً لكل نسخة من نسخ PerformanceEntry
:
const {
performance,
PerformanceObserver
} = require('perf_hooks');
const obs = new PerformanceObserver((list, observer) => {
//تُستدعى ثلاث مرات بشكل متزامن. تحوي اللائحة عنصر واحد
});
obs.observe({ entryTypes: ['mark'] });
for (let n = 0; n < 3; n++)
performance.mark(`test${n}`);
const {
performance,
PerformanceObserver
} = require('perf_hooks');
const obs = new PerformanceObserver((list, observer) => {
// تُستدعى مرة واحدة. تحوي اللائحة ثلاثة عناصر
});
obs.observe({ entryTypes: ['mark'], buffered: true });
for (let n = 0; n < 3; n++)
performance.mark(`test${n}`);
الصنف PerformanceObserverEntryList
يُستخدم الصنف PerformanceObserverEntryList
لتوفير وصول إلى نسخ PerformanceEntry
المُمررة إلى PerformanceObserver
.
performanceObserverEntryList.getEntries()
أُضيفت في الإصدار:8.5.0
- القيمة المعادة: <PerformanceEntry[]>
تعيد لائحة من كائنات PerformanceEntry
مرتبة زمنيًا بالنسبة إلى performanceEntry.startTime
.
performanceObserverEntryList.getEntriesByName(name[, type])
أُضيف في الإصدار: 8.5.0.
name
<string>type
<string>- القيمة المعادة: <PerformanceEntry[]>
تعيد لائحة من كائنات PerformanceEntry
مرتبة زمنيًا حسب performanceEntry.startTime
والتي فيها قيمة الخاصية performanceEntry.name
مساوية إلى name
، واختياريًا، تكون قيمةperformanceEntry.entryType
الخاصة بها مساويةً لtype
.
performanceObserverEntryList.getEntriesByType(type)
type
<string>
- القيمة المعادة: <PerformanceEntry[]>
تعيد لائحة من كائنات PerformanceEntry
بترتيب زمني بالنسبة إلى performanceEntry.startTime
والتي تكون فيها الخاصية performanceEntry.entryType
مساويةً إلى type
.
أمثلة
قياس المُدّة للعمليات غير المتزامنة
تستخدم الأمثلة التالية الخطافات غير المتزامنة وواجهات الأداء (الواجهات البرمجية للأداء Performance APIs) لقياس المدة الفعلية لعملية منتهية المهلة (متضمنة كمية الوقت [المُتطلبة] لتنفيذ دالة رد النداء callback).
'use strict';
const async_hooks = require('async_hooks');
const {
performance,
PerformanceObserver
} = require('perf_hooks');
const set = new Set();
const hook = async_hooks.createHook({
init(id, type) {
if (type === 'Timeout') {
performance.mark(`Timeout-${id}-Init`);
set.add(id);
}
},
destroy(id) {
if (set.has(id)) {
set.delete(id);
performance.mark(`Timeout-${id}-Destroy`);
performance.measure(`Timeout-${id}`,
`Timeout-${id}-Init`,
`Timeout-${id}-Destroy`);
}
}
});
hook.enable();
const obs = new PerformanceObserver((list, observer) => {
console.log(list.getEntries()[0]);
performance.clearMarks();
observer.disconnect();
});
obs.observe({ entryTypes: ['measure'], buffered: true });
setTimeout(() => {}, 1000);
قياس المدّة المأخوذة لتحميل الاعتماديات
يقيس المثال التالي مدة العملية require()
لتحميل الاعتماديات (dependencies):
'use strict';
const {
performance,
PerformanceObserver
} = require('perf_hooks');
const mod = require('module');
// محاكاة تصحيح/تشغيل الدالة المطلوبة
mod.Module.prototype.require =
performance.timerify(mod.Module.prototype.require);
require = performance.timerify(require);
// تفعيل المراقب
const obs = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach((entry) => {
console.log(`require('${entry[0]}')`, entry.duration);
});
obs.disconnect();
});
obs.observe({ entryTypes: ['function'], buffered: true });
require('some-module');