تحديد سبب «البطء» بـ PerfView وdotnet-trace ── مدخل عملي لتحقيق أداء .NET

· آخر تحديث: · · PerfView, dotnet-trace, ETW, تحقيق الأداء, .NET, CSharp, تحقيق الأخطاء, تطوير Windows, الاستشارات التقنية

سجل التعديلات (2 تحديثات، آخر تحديث 2 Sep، 2026)

سجل بالتغييرات التي أُجريت على هذا المقال. وحيثما حُفظت نسخة سابقة، تبقى متاحة للقراءة عبر رابط دائم يحمل معرّف DOI.

أُعيدَت الترجمة العربية كترجمة كاملة عن النص الياباني الأصلي، وأُضيفَت خريطة المعرفة.
أعيدت الترجمة كترجمة كاملة عن النص الياباني الأصلي. كانت النسخة العربية السابقة مختصراً يسقط أبواباً وجداول ورسوم Mermaid وتعليقات الأشكال وFAQ. أُعيدت هذه العناصر وفق الأصل الياباني، والادّعاءات التقنية مطابقة للنسخة اليابانية.
النشر الأول
الاستشهاد بهذا المقال(DOI: 10.5281/zenodo.21621666)

هذا المقال محفوظ على Zenodo. يرد أدناه معرّف DOI الذي يشير دائمًا إلى أحدث نسخة، ومعرّف DOI المثبَّت على النسخة التي تقرؤها.

غو كومورا (2026). تحديد سبب «البطء» بـ PerfView وdotnet-trace ── مدخل عملي لتحقيق أداء .NET. شركة كومورا سوفت ذ.م.م.. https://doi.org/10.5281/zenodo.21621666 https://comcomponent.com/ar/blog/perfview-dotnet-trace-performance-analysis/

DOI (أحدث نسخة)
10.5281/zenodo.21621666
DOI (هذه النسخة)
10.5281/zenodo.22241023

في المقال السابق مدخل إلى سجل أحداث Windows وETW تناولنا ماهية ETW وتعريف أحداث خاصة عبر EventSource، واعتبرنا التحليل عبر PerfView «خارج النطاق». هذا المقال امتداد لذلك. نتناول فيه إجراء تحديد الدالة المسؤولة عن السبب بـ PerfView وdotnet-trace، عندما يصبح تطبيق الأعمال «بطيئاً» أو «يلتصق بالمعالج» أو «يتجمد أحياناً».

موضوع هذا المقال تحقيق المعالج وزمن الاستجابة. عزل مشكلة الذاكرة التي تزداد بلا توقف في .NET: التمييز بين انتظار GC وتسرّب الذاكرة، ومشكلة الانهيار في قراءة تفريغ الانهيار بـ WinDbg + SOS.

1. الخلاصة أولاً

  • للـ«بطء» نوعان. بطء لأن المعالج مستنفد (CPU bound)، أو بطء لأن المعالج فارغ لكن العملية تُنتظَر (حظر). الأول يحتاج عيّنات المعالج، والثاني يحتاج جمع ThreadTime (تبديل السياق). إن نظرت جمع المعالج الافتراضي وحده فسبب الثاني لا يظهر.1
  • إن ترددت فابدأ بـ dotnet-trace. أداة عبر المنصات مبنية على EventPipe، ويمكن الجمع بلا امتيازات المدير إن كنت المستخدم نفسه الذي شغّل العملية المستهدفة.2 يمكن فتح .nettrace المجموع في PerfView أو Visual Studio.3
  • يلزم PerfView حين تريد رؤية الجهاز كله والشيفرة الأصلية ووقت الحظر. لأنه مبني على ETW، يعالج أحداث النواة ومكدس الشيفرة الأصلية أيضاً. في المقابل، بدء جلسة ETW يحتاج امتيازات المدير.3
  • عيّنات المعالج افتراضياً كل 1 مللي ثانية (لكل معالج). اقرأ العيّنة الواحدة ≈ 1 ms من زمن المعالج، واحكم بعد تجميع 1,000 عيّنة على الأقل (ويُفضَّل نحو 5,000). الدوال المتصدرة وقليل من العيّنات قد تكون مصادفة.1
  • تفسير الأرقام يبدأ كله من التمييز بين inclusive (الذات + ما تستدعيه) وexclusive (الذات وحدها). الدالة ذات exclusive الكبير هي «المكان الذي يستهلك المعالج فعلاً»، والدالة ذات inclusive الكبير هي «مكان ثقيل في ما تحتها».
  • قبل القياس ثبّت ماذا يعني «بطيء» في عملية واحدة. الجمع و«الثقل عام» لا يُقرأ. ثبّت العملية والزمن مثل «إخراج هذا التقرير يستغرق 40 ثانية» ثم اجمع. لفكرة مقارنة القياس قبل التحسين وبعده راجع أيضاً كيف تقارن سرعة إصدارات البرنامج مقارنة صحيحة على Windows.

مدخل الأعراض في جدول قرار.

العرض الأداة التي تُستخدم أولاً ما يُنظر إليه
المعالج مرتفع وملتصق dotnet-trace collect / CPU Stacks في PerfView الدوال ذات exclusive الكبير
المعالج منخفض لكن المعالجة بطيئة أو تتجمد PerfView (جمع ThreadTime) أي خيط انتظر ماذا فحُظر
بطء، لكنك تريد الاتجاه العام أولاً dotnet-counters استخدام المعالج، تكرار GC، امتلاء طابور ThreadPool
شبهة أن GC أكثر من اللازم dotnet-counters ← dotnet-trace (أحداث GC) عدد مرات GC وزمن التوقف، وأماكن التخصيص الكثيرة
معرفة أين يبطؤ مسار أعمال محدد أحداث EventSource الخاصة + ما سبق الزمن بين الأحداث الخاصة ومكدس ذلك المقطع

في المخطّط، يشير الخطّ المتّصل إلى علاقة قائمة دائماً، ويشير الخطّ المتقطّع إلى علاقة مشروطة (شروط قيامها مذكورة في شرح كلّ علاقة في الصفحة التفصيليّة). القائمة الكاملة للعلاقات (المجموع 20، مع الأدلّة ودرجة اليقين) وتعريفات المفاهيم الرئيسة مجمّعة في صفحة تفاصيل خريطة المعرفة (باليابانية). البيانات: JSON-LD / Turtle

2. ترتيب علاقة الأدوات ── ETW وEventPipe

تبدو الأدوات كثيرة، لكن الأساس اثنان فقط.

  • ETW (Event Tracing for Windows): أساس تتبع يخترق نظام التشغيل كله. يسجّل من النواة إلى التطبيق على المحور الزمني نفسه، لكن بدء الجلسة وإيقافها يحتاج امتيازات المدير، وهو خاص بـ Windows.3
  • EventPipe: آلية تتبع مدمجة في وقت تشغيل .NET. لا تحتاج امتيازات مدير وتعمل بالمثل على كل أنظمة التشغيل، لكن ما يُرى محصور في الشيفرة المُدارة ووقت التشغيل، ولا تُلتقط أحداث النواة ولا المكدس الأصلي.2
  dotnet-trace (EventPipe) PerfView (ETW)
امتيازات المدير غير لازمة (تجاه عملية المستخدم نفسه) لازمة
الهدف عملية .NET واحدة محددة الجهاز كله (كل العمليات + النواة)
المكدس الأصلي لا يُلتقط يُلتقط
وقت الحظر (تبديل السياق) لا يُلتقط يُلتقط بجمع ThreadTime
أنظمة التشغيل Windows / Linux / macOS Windows فقط

إن ثبتت هذه المقابلة في الذهن، يتحدد التوزيع طبيعياً: «اجمع أولاً بخفة بـ dotnet-trace. إن لم يكفِ فاجمع ETW كله بـ PerfView».

3. قبل الجمع ── انظر الاتجاه 10 دقائق بـ dotnet-counters

كثيراً ما يكون النظر أولاً إلى مقاييس وقت التشغيل الرئيسة بـ dotnet-counters أسرع من أخذ تتبع فوراً.4

dotnet tool install --global dotnet-counters
dotnet-counters ps
dotnet-counters monitor --process-id <PID> --counters System.Runtime

ما يُنظر إليه هنا: استخدام المعالج، حجم كومة GC وعدد مرات GC، طول طابور ThreadPool وعدد الخيوط، وعدد الاستثناءات. إن ظهر في هذه المرحلة اتجاه مثل «GC يعمل مرات كثيرة كل ثانية» أو «طابور ThreadPool يمتد بلا توقف»، أمكن تضييق نوع التتبع التالي (تخصيص أم حظر).

غير أن من يقيس لأول مرة لا يعرف «هل هذا الرقم شاذ». المعيار الأكثر موثوقية هو القيمة التي أخذتها بالأمر نفسه على تطبيقك في الحالة السليمة. كتصويب أولي قبل امتلاك ذلك المعيار، نلخص القراءة المستخدمة في العمل.5

العداد (System.Runtime) طريقة القراءة علامة تدعو إلى الشك
CPU Usage (%) استخدام المعالج للعملية كلها الالتصاق بقيمة تعادل نواة واحدة (نحو 25% على 4 نوى) دون حركة = خيط واحد يدور بلا توقف
GC Heap Size (MB) حجم الكومة المُدارة لا ينخفض بعد انتهاء المعالجة، ويصعد باستمرار = شبهة تسرّب
Gen 0 GC Count عدد مرات Gen 0 GC لكل فترة تحديث الكثرة نفسها ليست شذوذاً. إن كان Gen 2 GC Count مرة أو أكثر كل بضع ثوانٍ يلزم التحقيق
% Time in GC since last GC نسبة الزمن المنفق في GC منذ آخر GC إن تجاوزت العُشر باستمرار، فمستوى يستدعي النظر في تقليل التخصيص (تحقيق بـ --profile gc-verbose)
ThreadPool Queue Length عدد عناصر العمل المنتظرة في الحالة العادية يفترض أن يكون شبه 0. إن زاد ولم يعد فشبهة نضوب المجمّع = استدعاء حاجب
ThreadPool Thread Count عدد خيوط المجمّع إن بقي الحمل ثابتاً وازداد العدد درجياً = الأمر نفسه
Exception Count عدد حدوث الاستثناءات إن حدثت بانتظام، اشتبه في مواضع تستخدم الاستثناء كتدفق تحكم
Monitor Lock Contention Count عدد التنازع عند الحصول على القفل إن برز الازدياد فتنازع على الأقفال. انتقل إلى جمع ThreadTime في الفصل 6

المهم ليس العتبة نفسها بل «كيف تتحرك مع الزمن». القيمة التي تزيد وتنقص مع الحمل ثم تستقر سليمة، والقيمة التي لا تعود بعد إيقاف الحمل هي هدف التحقيق. قراءة اتجاهات الذاكرة مفصّلة في مقال التمييز بين انتظار GC وتسرّب الذاكرة.

4. أخذ تتبع بـ dotnet-trace

dotnet-trace أداة جمع مبنية على EventPipe.6 التثبيت والجمع الأساسي كما يلي.

dotnet tool install --global dotnet-trace
dotnet-trace ps
dotnet-trace collect --process-id <PID> --duration 00:00:00:30

إن لم تحدّد أي خيار، يُجمع بتكوين الملف الشخصي الافتراضي الذي يشمل أحداث وقت التشغيل الرئيسة وعيّنات الخيوط. أُلغي ملف شخصي كان اسمه cpu-sampling، والافتراضي الآن مزيج dotnet-common وdotnet-sampled-thread-time.6 حسب الغرض يمكن أيضاً اختيار --profile gc-verbose (عيّنات GC وتخصيص الكائنات) أو --profile gc-collect (تسجيل حدوث GC فقط بحمل منخفض).

لجمع موفّر EventSource الخاص الذي صنعته في المقال السابق معاً، أضف --providers.

dotnet-trace collect --process-id <PID> --providers KomuraSoft-OrderService

نتيجة الجمع ملف .nettrace. طرق الفتح ثلاث: Visual Studio أو PerfView، أو التحويل إلى صيغة speedscope والنظر في المتصفح.6

dotnet-trace convert trace.nettrace --format Speedscope

صيغة speedscope عرض رسم إطارات خفيف يُفتح في speedscope.app، وتناسب النظر الحدسي إلى «تحت أي دالة أُنفق الزمن».

لا تحتار في أيهما تفتح إن قررت لمن تعرض النتيجة.

الموقف الأنسب السبب
تضيق بنفسك حتى دالة السبب PerfView تجميع ByName، والتضييق بـ GroupPats/Fold، وقص النطاق الزمني مكتملة (الفصل 5)
تشارك مع الفريق أو العميل أن «هنا الثقل» speedscope لا يحتاج تثبيت PerfView، ويُفتح في المتصفح. رسم الإطارات ينقل الشكل بلا شرح
النظر في بيئة غير Windows speedscope PerfView خاص بـ Windows (الفصل 2). سلّم هذا لمطوّري macOS وLinux

أي أن PerfView للتحقيق، وspeedscope للمشاركة. التدقيق حتى اسم الدالة أقوى في عارض مكدس PerfView، لذلك ننتقل إلى الفصل التالي.

5. تحقيق المعالج بـ PerfView ── قراءة عارض المكدس

PerfView أداة تحقيق أداء تنشرها Microsoft مجاناً، وتعمل بتنزيل PerfView.exe واحد من صفحة الإصدارات على GitHub (لا تثبيت).7

5.1 الجمع

إن جمعت من الواجهة الرسومية، فالتدفق حتى أين تلمس الشاشة كما يلي.

  1. شغّل PerfView.exe كمدير (بدء جلسة ETW يحتاج امتيازات المدير3)
  2. من القائمة اختر Collect > Collect (الاختصار Alt+C). تُفتح نافذة الجمع وتطلب اسم ملف البيانات الذي سيُنشأ1
  3. حدّد محتوى الجمع من مربعات الاختيار في النافذة. كما هو افتراضياً تُجمع عيّنات المعالج وأحداث CLR الرئيسة. إن أردت تحقيق زمن الانتظار أيضاً، فعّل هنا مربع Thread Time (الفصل 6)1
  4. اضغط زر Start Collection
  5. أعد إنتاج العملية المراد فحصها (هذا هدف القياس، فلا تُدخل عمليات زائدة)
  6. اضغط زر Stop Collection. بعد إيقاف الجمع يجري دمج البيانات وحل الرموز، ويُنشأ .etl.zip بالاسم المحدد في الخطوة 2

لأداء الأمر نفسه من سطر الأوامر استخدم الشكل التالي (هذا أيضاً يُشغَّل كمدير3).

PerfView collect /nogui /acceptEULA /maxCollectSec:30

الجمع الافتراضي يشمل عيّنات معالج كل 1 مللي ثانية على كل المعالجات (مع مكدس الاستدعاء) وأحداث CLR الرئيسة.1 العبء الإضافي أثناء الجمع في التكوين الافتراضي يُقدَّر عموماً بنحو بضعة بالمئة.8

5.2 قراءة CPU Stacks

افتح نتيجة الجمع (.etl.zip)، واختر العملية المستهدفة في «CPU Stacks»، فيُفتح عارض المكدس.

العناصر كثيرة في النظرة الأولى، فطابق أولاً أين يوجد ماذا. ينقسم عارض المكدس إلى «حقول تصفية في الأعلى» و«شبكة تبديل تبويبات في الأسفل».

موضع الشاشة الاسم الدور
حقل الإدخال الأعلى Start / End النطاق الزمني المعروض (مللي ثانية من بدء التتبع). يُستخدم لتضييق المرة البطيئة وحدها (الفصل 7)
حقل الإدخال الأعلى IncPats / ExcPats نمط المكدسات المضمَّنة/المستبعدة. للتضييق على عملية أو وحدة محددة
حقل الإدخال الأعلى GroupPats قاعدة تجميع الأسماء. افتراضياً تُلخَّص المكتبات الخارجية فيبرز كودك
حقل الإدخال الأعلى Fold % / FoldPats طي العقد الصغيرة دون النسبة المحددة في الأب، لتقليل القائمة إلى حجم قابل للقراءة
التبويب الأسفل ByName تجميع لكل دالة. هنا تنظر أولاً
التبويب الأسفل CallTree تتبّع شجرة الاستدعاء من الأعلى. لرؤية التدفق الكلي
التبويب الأسفل Callers / Callees استخراج مصادر الاستدعاء / المستدعَيات للدالة المختارة فقط

أول ما يُنظر عمودان في تبويب ByName.

  • Exc (exclusive): عدد العيّنات التي كانت تلك الدالة نفسها قيد التنفيذ. هذا المكان الذي يستهلك المعالج فعلاً.
  • Inc (inclusive): مجموع عيّنات تلك الدالة وكل ما استُدعي منها. يدل على أن شيئاً تحتها ثقيل.

قالب القراءة: انظر أعلى Exc وفرّق «كودك أم وقت التشغيل والمكتبات». إن ظهر كودك في أعلى Exc، فخوارزمية تلك الدالة أو الحلقة هدف مباشر. إن تصدر System.String أو مسلسل JSON أعلى Exc، تتبعه بـ Inc في تبويب Callers واكتشف من أين في كودك يُستدعى بكثافة.

أمر مهم آخر هو التحقق من عدد العيّنات نفسه. عيّنة المعالج إحصاء بفاصل 1 ms، فقلّة العيّنات تجعل النتيجة رهينة المصادفة. كمعيار اجمع 1,000 عيّنة إجمالاً على الأقل، ويُفضَّل نحو 5,000، ثم احكم. إن نقصت فأعد تنفيذ العملية المستهدفة وأطل زمن الجمع.1

إن ظهرت أسماء دوال وحداتك كعناوين، فالرموز (PDB) لم تُحل. توفير PDB لنواتج البناء في متناول اليد هو إمكانية التحقيق نفسها. هذا الموضوع مفصّل في ما هو PDB (قاعدة بيانات البرنامج).

6. «المعالج فارغ لكنه بطيء» ── رؤية وقت الحظر بـ ThreadTime

أكثر من نصف «البطء» في العمل ليس المعالج بل الانتظار. انتظار قفل، انتظار استجابة DB أو HTTP، إدخال/إخراج ملف، انتظار يشبه الجمود عبر Task.Result. هذا النوع لا يظهر في عيّنة المعالج لأنه «زمن لم يُستخدم فيه المعالج أصلاً»، لذلك لا يظهر السبب في الجمع الافتراضي.

في PerfView، إن فعّلت خيار Thread Time عند الجمع، تُسجَّل أحداث تبديل السياق إضافة، فيمكن تتبع «زمن استخدام المعالج» و«زمن الحظر» لكل خيط معاً.1

طرق التفعيل اثنتان، واجهة رسومية وسطر أوامر، والنتيجة واحدة.

  • في الواجهة الرسومية: في الخطوة 2 من 5.1 افتح نافذة Collect > Collect (Alt+C)، فعّل مربع Thread Time ثم اضغط Start Collection. الدليل الرسمي أيضاً ينص صراحة: «إن أردت تحقيق زمن الساعة الجدارية، يلزم ضبط مربع Thread Time في نافذة الجمع».1 الغفلة عن هذا والجمع بالافتراضي ثم الحيرة لأن «وقت الحظر لا يظهر» هي العتبة الأولى.
  • في سطر الأوامر: أضف المفتاح /threadTime.
PerfView collect /nogui /acceptEULA /threadTime /maxCollectSec:30

في التحليل افتح عرض «Thread Time Stacks». عارض المكدس نفسه كما في CPU Stacks، لكن الفرق أن العيّنات تشمل ليس زمن المعالج فقط بل أيضاً BLOCKED_TIME (زمن الحظر). بعد تضييق النطاق الزمني للعملية البطيئة، انظر في أي مكدس (أي انتظار) تراكم BLOCKED_TIME للخيط الذي تولّى المعالجة، فيظهر التفصيل بشكل «من أصل 40 ثانية، 35 ثانية كانت انتظار استدعاء HTTP هذا».

أعراض تجمّد الواجهة (ثوانٍ بلا استجابة عند العملية) أيضاً هويتها في الغالب حظر خيط الواجهة. بعد تحديد وجهة حظر خيط الواجهة بـ ThreadTime، يُنقل الحل الدائم إلى تصميم يجعل الانتظار المتزامن لاتزامنياً. ترتيب جانب التصميم هذا في ترتيب async وخيط الواجهة في WPF/WinForms في ورقة واحدة.

تنبيه: جمع ThreadTime يسجّل حدثاً عند كل تبديل سياق، فيزداد حجم البيانات بوضوح عن الجمع الافتراضي. قصّر زمن الجمع، وتجنّب الجمع الطويل في الإنتاج.

7. الجمع مع EventSource ── قص «أي مقطع بطيء» بلغة العمل

CPU Stacks وThread Time كلاهما تجميع للعملية كلها. إن أردت القص بوحدة معالجة الأعمال مثل «أين البطء داخل معالجة طلب واحد»، تعمل أحداث Start/Stop في EventSource التي تناولها المقال السابق.

حتى يمكن تجربة هذا الفصل دون قراءة المقال السابق، نضع الحد الأدنى من الشيفرة لصنع الموفّر المستهدف بنفسك. --providers KomuraSoft-OrderService في الفصل 4 يشير إلى هذا Name.

using System.Diagnostics.Tracing;

// [EventSource(Name = ...)] がETW/EventPipeから見えるプロバイダー名になる
[EventSource(Name = "KomuraSoft-OrderService")]
public sealed class OrderServiceEventSource : EventSource
{
    public static readonly OrderServiceEventSource Log = new OrderServiceEventSource();

    [Event(1, Level = EventLevel.Informational)]
    public void OrderProcessingStart(string orderId) => WriteEvent(1, orderId);

    [Event(2, Level = EventLevel.Informational)]
    public void OrderProcessingStop(string orderId) => WriteEvent(2, orderId);
}

جهة الاستدعاء تكتفي بأن تحصر المقطع المراد قياسه.

OrderServiceEventSource.Log.OrderProcessingStart(orderId);
try
{
    ProcessOrder(orderId); // 計測したい業務処理
}
finally
{
    OrderServiceEventSource.Log.OrderProcessingStop(orderId);
}

اجعل أسماء الدوال على نمط Start / Stop واجعل معرّفات الأحداث متسلسلة، فيسهل قراءة المقطع كزوج في عرض Events في PerfView. إخراج Stop حتماً في finally حتى لا تبقى المرة التي خرجت باستثناء «مقطعاً لا ينتهي». طريقة كتابة تعريف الأحداث بالتفصيل (قيود أنواع الوسائط، والتمييز بين EventLevel وKeywords) في المقال السابق.

على فرض وجود هذا التجهيز، يسير التحقيق بالترتيب التالي.

  • جهّز في التطبيق أحداثاً مثل OrderProcessingStart / OrderProcessingStop (الشيفرة أعلاه)
  • تحقق من زمن تلك الأحداث في عرض «Events» في PerfView، وضيّق النطاق الزمني لعارض المكدس (تصفية Start/End) على ذلك المقطع
  • اقرأ تفصيل زمن المعالج/الحظر في النطاق المضيَّق

بهذا تحلّل «تلك المرة البطيئة» وحدها، ولا تُدفن في ضوضاء الحالة العادية. الأحداث الخاصة تُجمع بالمثل عبر dotnet-trace، فإن أدخلت التجهيز مرة واحدة سرت طريقة الفحص نفسها على جهاز التطوير وفي الإنتاج. في العمل، صعوبة تحقيق الأداء لا تُحسم بمهارة الأداة بقدر ما تُحسم بـ«هل لنقاط الرصد وجود في التطبيق».

الخلاصة

  • نقطة الانطلاق تقسيم «البطء» إلى CPU bound وحظر. الأول يظهر بعيّنات المعالج (العيّنة ≈ 1 ms)، والثاني لا يظهر إلا بجمع ThreadTime.
  • الأساس: أولاً dotnet-trace بلا امتيازات مدير، وPerfView إن لزم الجهاز كله والشيفرة الأصلية ووقت الحظر. قراءة .nettrace المجموع في PerfView أيضاً أسلوب ثابت.
  • نواة قراءة عارض المكدس التمييز بين exclusive وinclusive، وتحقق دائماً أن عدد العيّنات كافٍ.
  • إن أمكن قص مقطع معالجة الأعمال بأحداث EventSource الخاصة، ارتفعت دقة التحقيق درجة.

تتعامل شركة كومورا سوفت ذ.م.م. مع تحقيق مشكلات أداء تطبيقات Windows للأعمال مثل «بطيء» و«يتجمد» و«يلتصق بالمعالج»، ومع استشارة التجهيز والتصميم لجعل القياس ممكناً. إن توفّرت خطوات إعادة الإنتاج وملف التتبع، يمكن طلب التحليل من تلك النقطة فقط.

مقالات ذات صلة

مجالات الاستشارة ذات الصلة

المراجع

  1. GitHub، PerfView User’s Guide. حول أن الجمع الافتراضي عيّنات معالج بفاصل 1 مللي ثانية لكل معالج (مع مكدس الاستدعاء)، وأن الحكم يُفضَّل بعد نحو 1,000 إلى 5,000 عيّنة، وأن خيار ThreadTime يجمع تبديل السياق فيمكن تحليل وقت الحظر أيضاً (يمكن الرجوع إليه أيضاً من Help داخل PerfView).  2 3 4 5 6 7 8

  2. Microsoft Learn، EventPipe Overview. حول أن EventPipe آلية لتتبع تطبيقات .NET دون الاعتماد على مكوّنات عالية الامتياز مثل امتيازات المدير، وأن الهدف محصور في الشيفرة المُدارة ووقت التشغيل، وأن أحداث النواة والمكدس الأصلي لا تُلتقط.  2

  3. Microsoft Learn، Collect and View EventSource Traces. حول أن جمع تتبع ETW يحتاج دائماً امتيازات المدير، وأن PerfView وVisual Studio يستطيعان فتح ملفات .nettrace.  2 3 4 5

  4. Microsoft Learn، dotnet-counters diagnostic tool. حول مراقبة مقاييس المعالج وGC وThreadPool وغيرها للعملية قيد التشغيل عبر عدادات System.Runtime. 

  5. Microsoft Learn، Well-known EventCounters in .NET. حول قائمة العدادات التي ينشرها System.Runtime ومعنى كل عداد (CPU Usage، GC Heap Size، Gen 0/1/2 GC Count، % Time in GC since last GC، ThreadPool Queue Length، ThreadPool Thread Count، Exception Count، Monitor Lock Contention Count وغيرها). 

  6. Microsoft Learn، dotnet-trace diagnostic tool. حول استخدام أمر collect، والملفات الشخصية المفعّلة افتراضياً (dotnet-common / dotnet-sampled-thread-time) وإلغاء ملف cpu-sampling، وملفات مثل gc-verbose / gc-collect، والتحويل إلى صيغتي Speedscope وChromium.  2 3

  7. GitHub، microsoft/perfview. حول أن PerfView أداة تحليل أداء مجانية لتحقيق مشكلات الأداء المرتبطة بالمعالج والذاكرة، وأن الملف التنفيذي يُحصل عليه مباشرة من صفحة الإصدارات. 

  8. GitHub، microsoft/perfview Issue #598. حول شرح أحد مسؤولي صيانة PerfView أن العبء الإضافي عند الجمع الافتراضي نحو 3% عموماً، وإمكانية خفض الحمل بضبط فاصل العيّنات عبر /CpuSampleMSec. 

أحدث المقالات التي تشترك في نفس الوسوم. عمّق فهمك بمواضيع مرتبطة.

ترتبط هذه المقالة بشكل طبيعي بصفحات الخدمات التالية.

الأسئلة الشائعة

أسئلة شائعة حول موضوع هذه المقالة.

أي الأداتين ينبغي استخدامها، PerfView أم dotnet-trace؟
يُنصح بالبدء بتجربة dotnet-trace أولاً. يعمل بلا امتيازات المدير، ويمكنه الجمع مستهدفاً العملية المعنية فقط، والتشغيل بسطر أمر واحد. في المقابل، إن أردت رؤية مكدس الشيفرة الأصلية (native)، أو حالة الجهاز كاملة (أثر العمليات الأخرى أو النواة)، أو تتبّع وقت الحظر بوحدة تبديل السياق (context switch)، يلزم PerfView المبني على ETW. ومن الشائع أيضاً الجمع بين الأداتين: جمع ملف .nettrace ثم فتحه في PerfView للتحليل.
ما العلاقة بأداة التحليل (profiler) في Visual Studio؟
إن كانت المشكلة قابلة لإعادة الإنتاج على جهاز التطوير، فأداة استخدام المعالج وأداة الذاكرة في Visual Studio أسهل، وكثيراً ما تكفيان أولاً. يعمل PerfView وdotnet-trace حين لا يمكن تثبيت Visual Studio (جهاز تحقق أو إنتاج)، أو حين تريد فصل الجمع عن التحليل على جهازين، أو حين تريد رؤية أحداث ETW أيضاً (بما فيها EventSource الخاص بك أو أحداث النواة). كذلك يستطيع Visual Studio فتح ملف .nettrace الذي يخرجه dotnet-trace.
هل يجوز التشغيل على خادم الإنتاج؟
صُمّمت كلتا الأداتين مع افتراض الجمع القصير في الإنتاج، لكن ذلك ليس بلا شروط. حدّد وقت الجمع بعشرات الثواني إلى بضع دقائق، وجرّب أولاً الأمر نفسه في بيئة التحقق لتأكيد العبء الإضافي وحجم الملف، وتحقق من المساحة المتبقية على القرص. خصوصاً جمع ThreadTime (تبديل السياق) وتتبع التخصيص يحتويان كماً كبيراً من الأحداث، فيتضخم الملف بسرعة. كذلك يحتوي التتبع معلومات مثل وسائط سطر الأوامر، فتعامل بحذر مع الملف الملتقط.
كيف يُوزَّع الاستخدام بينها وبين WPR/WPA؟
WPR (Windows Performance Recorder) وWPA (Windows Performance Analyzer) أداتا تحقيق أقرب إلى نظام التشغيل، مبنيتان على ETW نفسه. في التحليل المفصّل على مستوى نظام التشغيل كله - مثل إدخال/إخراج القرص، والطاقة، ووقت بدء التشغيل - يتفوق WPR/WPA، بينما في تحقيق المعالج وGC ووقت الحظر لتطبيق .NET يكون PerfView المحسَّن لعرض الشيفرة المُدارة أسهل قراءة. إن كان الهدف تحقيق تطبيق أعمال، فإن PerfView وdotnet-trace يكفيان في معظم الحالات.

الملف الشخصي للمؤلف

صفحة الملف الشخصي لمؤلف المقالة.

غو كومورا

مؤسّس شركة كومورا سوفت ذ.م.م.

يركّز على تطوير برامج ويندوز، والاستشارات التقنية، والتحقيق في الأخطاء، ويتميّز في المشاريع التي تبقى فيها الأصول القديمة ناشطة، وفي تشخيص الأعطال التي يصعب تحديد سببها.

العودة إلى المدونة