ماذا تعني «استخدام الذاكرة» في Windows فعليّاً ── قراءة Working Set وPrivate Bytes وCommit وملفّ الصفحات قراءة صحيحة

· · Windows, تطوير Windows, إدارة الذاكرة, Working Set, Private Bytes, Commit, ملفّ الصفحات, مراقبة الأداء, استكشاف الأعطال, Sysinternals

يعرض مدير المهام «ذاكرة» عمليّة ما على أنّها 1.2GB. ومع ذلك يُظهر Process Explorer Working Set بقيمة 1.5GB وPrivate Bytes بقيمة 2.4GB، وSize في VMMap أكبر بعد. وعند النظر إلى النظام ككلّ يُقرأ «Committed 19.6/31.8GB».

فكم غيغابايت من الذاكرة يستخدم هذا التطبيق في النهاية؟

الجواب أنّ الرقم الذي ينبغي النظر إليه يعتمد على ما تريد معرفته فعلاً. يختلف المؤشّر بحسب ما إذا كنت تريد الكمّيّة المقيمة حاليّاً في RAM، أو الكمّيّة المخصَّصة خصّيصاً لتلك العمليّة، أو الكمّيّة التي وعد النظام بمواصلة دعمها مستقبلاً، أو مجرّد نطاق العناوين الافتراضيّة الذي حُجز.

ما يجعل مؤشّرات ذاكرة Windows مربكة هو أنّها تُعرَض كلّها تحت الكلمة نفسها، «ذاكرة»، رغم أنّها تقيس في الواقع المحاور المنفصلة الآتية.

  • مقدار مساحة العناوين المستخدَمة
  • مقدار Commit المستهلك
  • ما إذا كانت الصفحة مقيمة حاليّاً في RAM الفيزيائيّة
  • ما إذا كانت الصفحة خاصّة بالعمليّة، أم قابلة للمشاركة
  • مقدار التخصيص الإضافيّ الذي ما زال النظام ككلّ قادراً على دعمه

يستهدف هذا المقال من يحقّق في تزايد ذاكرة التطبيق أو نقص الذاكرة على مستوى النظام في Windows 10/11 وWindows Server الحاليّ، ويربط في صورة واحدة العلاقات بين Working Set وPrivate Working Set وPrivate Bytes وCommit وVirtual Bytes وملفّ الصفحات وAvailable وأعطال الصفحات.

إجراء تتبّع سبب عدم جمع كائنات .NET مشروح بالتفصيل في «التمييز بين انتظار GC وتسريب الذاكرة في .NET»، والتشغيل العمليّ لـ VMMap وProcess Explorer مشروح في «Process Explorer / Handle / VMMap في الممارسة». يركّز هذا المقال على المقدّمة المشتركة للاثنين: كيفيّة قراءة الأرقام من جانب نظام تشغيل Windows.

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

  • Working Set هو مجموعة الصفحات المقيمة حاليّاً في RAM. لا يشمل صفحات العمليّة الخاصّة فحسب، بل أيضاً الصفحات التي يمكن مشاركتها مع عمليّات أخرى، مثل شيفرة DLL والملفّات المعيَّنة في الذاكرة.1
  • Private Working Set هو الجزء من Working Set الذي ينتمي حاليّاً إلى تلك العمليّة وحدها. يصلح تقريباً لـ«RAM التي تحتلّها هذه العمليّة وحدها الآن»، لكنّه ليس الكمّيّة الكلّيّة التي خصّصها التطبيق.2
  • Private Bytes هو كمّيّة الـ Commit الخاصّة بتلك العمليّة. وهو مؤشّر منفصل عن كون الذاكرة مقيمة حاليّاً في RAM. وحقل PagefileUsage في بنية Win32 API يمثّل هو أيضاً، على Windows الحاليّ، Commit Charge نفسه عمليّاً، وليس عدد البايتات المكتوبة فعليّاً إلى ملفّ الصفحات.2
  • «Committed X/Y» في مدير المهام يعرض X على أنّه إجمالي Commit النظام الحاليّ وY على أنّه سقف الـ Commit. X ليس استخدام ملفّ الصفحات. ويُحدَّد Y تقريباً بمجموع RAM وملفّ الصفحات.3
  • Reserve وCommit شيئان مختلفان. مجرّد حجز نطاق عناوين افتراضيّة يضع ذلك النطاق جانباً للاستخدام المستقبليّ؛ ولا يستهلك القدر نفسه لا من RAM ولا من سقف الـ Commit.45
  • Page Fault لا يعني بالضرورة إدخال/إخراج قرص. هناك أعطال ليّنة تُحلّ داخل RAM، وأعطال صلبة تقرأ من ملفّ الصفحات وملفّات التنفيذ والملفّات المعيَّنة في الذاكرة وما شابه.16
  • يُحكَم على تسريب الذاكرة لا من قراءة واحدة بل من الاتّجاه عند تكرار الحمل نفسه. راقب خصوصاً ما إذا كان Private Bytes وتفصيله يواصلان الارتفاع درجةً درجةً حتّى بعد انتهاء المعالجة، دون العودة إلى الحالة المستقرّة نفسها.

بجملة واحدة: Working Set هو «الكمّيّة الموجودة الآن في RAM»، وPrivate Bytes هو «الكمّيّة الموعودة خصّيصاً لهذه العمليّة»، وCommit هو «الكمّيّة التي وعد بها النظام ككلّ».

اختيار مؤشّر ذاكرة Windows المناسبالمؤشّر الذي يُنظَر إليه يعتمد على ما إذا كنت تريد إقامة RAM أو Commit خاصّاً بالعمليّة أو Commit على مستوى النظام أو نطاق عناوين افتراضيّالكمّيّة الآن في RAMالكمّيّة الموعودة الخاصّة بالعمليّةالكمّيّة الموعودة على مستوى النظامنطاق العناوين المحجوزما الذي تريد معرفته عن استخدام الذاكرةWorking SetPrivate BytesSystem CommitVirtual Bytes / Reservedالإقامة في RAM الفيزيائيّةCommit خاصّ بالعمليّةالمقارنة مع Commit Limitمساحة العناوين الافتراضيّة

الشكل 1: فكّك الملاحظة «الذاكرة مرتفعة» أوّلاً إلى أربعة أسئلة منفصلة.

2. تقسيم «استخدام الذاكرة» إلى أربعة محاور

في البداية، فكّر في ذاكرة Windows لا على أنّها «شريط واحد» بل على أربعة محاور.

أربعة محاور مستقلّة لتصنيف صفحة واحدةافحص حالة العنوان الافتراضيّ، وتغطية الصفحات المُلتزَم بها، والإقامة في RAM الفيزيائيّة، وقابليّة المشاركة مع عمليّات أخرى، كلّاً على حدةانظر إلى صفحة واحدة على أربعة محاورحالة العنوانFree / Reserved / CommittedالتغطيةPage-file-backed / File-backedإقامة RAMResident / Not residentقابليّة المشاركةPrivate / Shareable

الشكل 2: حتّى للصفحة الواحدة، تُحدَّد حالة العنوان والتغطية والإقامة وقابليّة المشاركة كلّ على حدة.

Mapped ليست حالة عنوان إلى جانب Free وReserved وCommitted ── بل فئة من المناطق. صفحات العرض المعيَّن يمكن أن تكون Committed أيضاً. وبالمثل، Private ليست وسيط تغطية بل تصنيف لقابليّة المشاركة. فاقرأ التغطية على أنّها Page-file-backed أو File-backed، وقابليّة المشاركة على أنّها Private أو Shareable، كلّاً على حدة.

بجمع هذه المحاور الأربعة تكون علاقة المؤشّرات التمثيليّة كما يلي.

حالة الصفحة Working Set Private Working Set Private Bytes عائلة Virtual Bytes
خاصّة بالعمليّة، مُلتزَم بها، مقيمة في RAM مضمَّنة مضمَّنة مضمَّنة مضمَّنة
خاصّة بالعمليّة، مُلتزَم بها، غير مقيمة في RAM غير مضمَّنة غير مضمَّنة مضمَّنة مضمَّنة
صفحة مشتركة لـ DLL أو ملفّ معيَّن، مقيمة في RAM مضمَّنة غير مضمَّنة عموماً غير مضمَّنة عموماً مضمَّنة
Reserved دون Commit غير مضمَّنة غير مضمَّنة غير مضمَّنة قد تُضمَّن
نطاق عناوين غير مستخدَم غير مضمَّنة غير مضمَّنة غير مضمَّنة عادةً غير مضمَّنة
ربط أنواع الصفحات بمؤشّرات الذاكرة الرئيسةيبيّن أيّ مؤشّرات تضمّ الصفحات الخاصّة المقيمة، والخاصّة غير المقيمة، والمشتركة المقيمة، والنطاقات المحجوزة فقطPrivate، مُلتزَم، مقيم في RAMPrivate، مُلتزَم، غير مقيم في RAMصفحة مشتركة، مقيمة في RAMReserved، غير مُلتزَمWorking SetPrivate Working SetPrivate Bytesعائلة Virtual Bytes

الشكل 3: Working Set وPrivate Bytes يعدّان مجموعتَي صفحات مختلفتين، لذا ليستا في علاقة احتواء بسيطة.

النقطة المهمّة هنا أنّ Working Set وPrivate Bytes ليستا في علاقة احتواء بسيطة.

يشمل Private Bytes صفحات خاصّة بالعمليّة لكنّها غير مقيمة حاليّاً في RAM. أمّا Working Set فيشمل صفحات مشتركة ── مثل شيفرة DLL والذاكرة المشتركة ── لا يعدّها Private Bytes أصلاً. لذلك، بحسب العمليّة واللحظة، قد يكون Working Set أكبر من Private Bytes، أو العكس.

كذلك، جمع Working Set لعدّة عمليّات ببساطة قد يعدّ الصفحة الفيزيائيّة نفسها ── مثل DLL مشتركة ── أكثر من مرّة. «مجموع Working Set لكلّ عمليّة يساوي RAM المستخدَمة» لا يصمد بالضرورة.

3. مساحة العناوين الافتراضيّة ── Reserve وCommit شيئان مختلفان

3.1. العنوان الافتراضيّ ليس عنوان RAM فيزيائيّاً

لكلّ عمليّة مساحة عناوين افتراضيّة خاصّة بها. المؤشّر الذي يتعامل معه التطبيق لا يدلّ مباشرة على موضع في RAM الفيزيائيّة؛ يستخدم Windows جداول الصفحات لربط العناوين الافتراضيّة بصفحات فيزيائيّة أو ببيانات على ملفّ.7

لذلك، حتّى على حاسوب مثبَّت فيه 64GB من RAM، تكون مساحة العناوين الافتراضيّة التي تستطيع عمليّة 32-بت معيّنة استخدامها أصغر بكثير عادةً. وبالمقابل، من الطبيعيّ أيضاً أن تملك عمليّة 64-بت مساحة عناوين افتراضيّة أكبر من RAM الفيزيائيّة.

3.2. Reserved يعني فقط أنّ «العنوان قد حُجز»

MEM_RESERVE في VirtualAlloc يحجز نطاقاً متواصلاً من العناوين الافتراضيّة للاستخدام المستقبليّ. في هذه المرحلة لا يُربَط تخزين فيزيائيّ بالصفحات، ولا يمكن قراءة النطاق أو الكتابة إليه.45

مثلاً، حتّى إن حجزت قاعدة بيانات أو بيئة تشغيل نطاق عناوين 8GB للنموّ المستقبليّ، فإنّ ذلك وحده لا يستهلك 8GB من RAM ولا 8GB من Private Bytes.

3.3. Committed وعد بـ«الدعم عندما تدعو الحاجة»

MEM_COMMIT هو العمليّة التي تضع صفحة افتراضيّة في حالة Committed وتجعل Windows يعد بتوفير التغطية اللازمة. ما إذا كانت القراءة أو الكتابة أو التنفيذ مسموحة فعليّاً تقرّره حماية الصفحة على حدة ── PAGE_READONLY وPAGE_READWRITE وPAGE_EXECUTE وPAGE_NOACCESS وما شابه ── لذا فإنّ كون الصفحة Committed بحدّ ذاته لا يعني «قابلة للقراءة والكتابة». لحظة الالتزام تُحتسَب ضمن Commit Charge للنظام، لكن الصفحة الفيزيائيّة الفعليّة قد لا تُعيَّن حتّى أوّل وصول. الصفحة التي تُلمَس أوّل مرّة تُهيَّأ بالأصفار، وتمرّ بـ demand-zero fault، وتدخل Working Set.51

لذلك، رغم أنّنا نسمّي الأمر «تخصيصاً» في الحالتين، فهناك في الواقع ثلاث مراحل الآتية.

ثلاث مراحل من Reserve عبر Commit إلى إقامة RAMيبيّن تدفّق حجز عنوان افتراضيّ، ثمّ الالتزام بالصفحة، ثمّ تعيين صفحة فيزيائيّة عند أوّل وصول ودخول Working SetMEM_COMMITأوّل وصول، demand-zero faultإن لم يُوصَل إليها قطّMEM_RESERVE - حجز نطاق عناوينينعكس في عائلة Virtual BytesCommitted - قابل للوصول بحسب حماية الصفحةينعكس في Private Bytes / System Commitتعيين صفحة فيزيائيّة، إقامة في RAMينعكس في Working SetCommitted لكن غير مقيمة

الشكل 4: Reserve وCommit وأوّل وصول أحداث منفصلة، وكلّ منها يحرّك مؤشّراً مختلفاً.

هذه المراحل الثلاث تحرّك أرقام عائلة Virtual Bytes وPrivate Bytes وWorking Set على حدة، على الترتيب.

3.4. لماذا قد يحدث OutOfMemory رغم توفّر RAM حرّة

نجاح تخصيص الذاكرة لا يُحدَّد بـ RAM الحرّة وحدها.

  • العمليّة استنفدت مساحة عناوينها الافتراضيّة
  • لا يوجد نطاق عناوين حرّ بالحجم المطلوب متواصل
  • وصل Commit Charge على مستوى النظام إلى Commit Limit
  • لـ Job Object أو حاوية أو بيئة تشغيل أو مكتبة حدّ خاصّ بها
  • العمليّة 32-بت
  • كومة الأصل native مجزَّأة

حتّى على Windows 64-بت، مساحة العناوين الافتراضيّة لعمليّة 32-بت في وضع المستخدم تكون عادةً 2GB إن لم يُضبَط IMAGE_FILE_LARGE_ADDRESS_AWARE. وتطبيق 32-بت بهذا العلم يستطيع استخدام حتّى 4GB على Windows 64-بت.8

لذلك فإنّ «الحاسوب يملك 20GB من RAM الحرّة، ومع ذلك يفشل تطبيق 32-بت عند نحو 1.6GB» ليس تناقضاً. قد لا تكون المشكلة في RAM أصلاً، بل تجزئة مساحة العناوين أو الاصطدام بحدّ صارم.

4. Working Set ── الصفحات الموجودة الآن في RAM

Working Set هو مجموعة الصفحات، ضمن مساحة العناوين الافتراضيّة للعمليّة، المقيمة حاليّاً في RAM الفيزيائيّة.1

هذه المجموعة خليط ممّا يلي.

  • كومة العمليّة ومكدّسها الخاصّان
  • شيفرة EXE وDLL والبيانات للقراءة فقط
  • الملفّات المعيَّنة في الذاكرة
  • الذاكرة المشتركة
  • الصفحات التي صارت خاصّة بتلك العمليّة بعد النسخ عند الكتابة
  • الصفحات التي لمستها بيئة التشغيل والمكتبات المختلفة

4.1. نموّ Working Set لا يعني بالضرورة تخصيصاً جديداً

الوصول أوّل مرّة إلى صفحة كانت مُلتزَماً بها أصلاً قد يزيد Working Set وحده بينما يبقى Private Bytes بلا تغيير. وبالمثل، عندما يُعيَّن ملفّ كبير في الذاكرة ويُقرأ بالتتابع، تدخل صفحات مغطّاة بالملفّ إلى Working Set بينما لا يكاد Private Bytes يزيد.

وبالعكس، عندما يُجري Windows Trim لـ Working Set استجابةً لضغط الذاكرة، ينكمش Working Set وحده بينما يحتفظ التطبيق منطقيّاً بالذاكرة نفسها. لمسها لاحقاً يعيدها عبر Page Fault.

لذلك فإنّ هبوط Working Set لا يعني بالضرورة «أنّ التطبيق حرّرها»، والارتفاع لا يعني بالضرورة «أنّ التطبيق خصّصها حديثاً».

تدفّق نمطيّ يرتفع فيه Working Set وينخفض وحدهالصفحة المُلتزَم بها نفسها تدخل RAM عند أوّل وصول، وتصير غير مقيمة عند Trim، وتعود عند إعادة الوصول، بينما يظلّ Private Bytes محسوباً طوال الوقتأوّل وصولTrim تحت ضغط الذاكرةPage Fault عند إعادة الوصولالصفحة المُلتزَم بها نفسهامقيمة في RAMغير مقيمةمضمَّنة في Working Setغير مضمَّنة في Working Setمحسوبة في Private Bytes طوال الالتزام

الشكل 5: Working Set يرتفع وينخفض مع الإقامة، لكن Private Bytes لا ينخفض ما دام Commit الصفحة نفسها باقياً.

4.2. Working Set يشمل صفحات مشتركة

إذا شاركت 10 عمليّات صفحات شيفرة DLL نفسها، يمكن أن تظهر تلك الصفحة في Working Set لكلّ عمليّة، رغم وجود نسخة واحدة فقط في RAM الفيزيائيّة. تجاوز مجموع Working Set لـ RAM المثبَّتة ليس علامة اضطراب فوريّة.

إن أردت الاقتراب من «RAM التي تحتلّها هذه العمليّة وحدها الآن»، فانظر إلى Private Working Set. ومع ذلك، هذا أيضاً ليس «كلّ الذاكرة التي خصّصتها تلك العمليّة» ── بل بدقّة الصفحات الخاصّة المقيمة حاليّاً.

4.3. خفض Working Set قسراً لا يصلح تسريباً

يمكن استخدام EmptyWorkingSet أو SetProcessWorkingSetSize لطرد صفحات من Working Set لعمليّة. لكن هذه ليست عمليّة تحرّر الـ Commit أو تُسقط المراجع على الكومة. ينخفض استخدام RAM الظاهريّ بينما يبقى Private Bytes بلا تغيير، وقد يُطلق الوصول التالي دفعة من أعطال الصفحات.9

إذا انكمش رقم مدير المهام فقط مباشرة بعد الضغط على زرّ «تقليل الذاكرة»، ثمّ عاد فوراً عند استئناف العمل، فقد يكون مجرّد Trim لـ Working Set لا «تحريراً» فعليّاً.

5. Private Bytes ── كمّيّة الـ Commit الخاصّة بعمليّة

Private Bytes هو كمّيّة الذاكرة الافتراضيّة المُلتزَم بها حصراً لتلك العمليّة. يمثّل Commit Charge لا يمكن مشاركته مع عمليّة أخرى، ولا يهمّ إن كان مقيماً حاليّاً في RAM. في PROCESS_MEMORY_COUNTERS_EX من Microsoft، يقابل PrivateUsage هذه القيمة.102

لدى Win32 API أيضاً حقل باسم مربك، PagefileUsage، لكن التوثيق الحاليّ يعرّفه بأنّه «Commit Charge لتلك العمليّة» ويقول إنّه القيمة نفسها لـ PrivateUsage. بعبارة أخرى، Private Bytes بقيمة 2GB لا يعني «كُتب 2GB إلى pagefile.sys».2

يتأثّر Private Bytes عادةً بما يلي.

  • Commit الكومة الأصليّة التي يستخدمها HeapAlloc وmalloc وnew وما شابه
  • Private Data المُلتزَم به مباشرة بـ VirtualAlloc
  • المنطقة المُلتزَم بها من كومة GC في .NET
  • الجزء المُلتزَم به فعليّاً من مكدّس خيط
  • Commit Charge للعرض كلّه عند تعيين عرض نسخ-عند-الكتابة(FILE_MAP_COPY
  • المخازن الخاصّة التي تحتفظ بها المكتبات وحزم تطوير الأجهزة داخليّاً

في عرض نسخ-عند-الكتابة المُنشأ بـ FILE_MAP_COPY، يمكن لكلّ صفحة أن تصير خاصّة في النهاية، لذا يحجز Windows عند التعيين Commit Charge كافياً لتغطية العرض كلّه بملفّ الصفحات. لذلك يمكن أن يرتفع System Commit وCommit Charge للعمليّة(Private Bytes)بحجم العرض كلّه حتّى قبل أن يُنشئ أيّ كتابة نسخة خاصّة فعليّاً.11

5.1. لماذا لا ينخفض Private Bytes بعد free أو GC

حتّى عندما تُ«حرَّر» الذاكرة من وجهة نظر التطبيق، قد لا تُعيد بيئة التشغيل أو مخصِّص الكومة تلك المنطقة إلى نظام التشغيل بـ Decommit، بل تبقيها لإعادة الاستخدام لاحقاً. في تلك الحالة يبقى Private Bytes مرتفعاً رغم أنّ المنطقة قابلة لإعادة الاستخدام داخليّاً داخل التطبيق.

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

لذلك فإنّ ارتفاع Private Bytes وحده لا يثبت تسريباً. ما ينبغي النظر إليه مقارنة عبر الزمن:

  1. كرّر المعالجة نفسها العدد نفسه من المرّات
  2. انتظر المدّة نفسها بعد المعالجة
  3. افحص ما إذا عاد Private Bytes إلى المستوى نفسه، أو استقرّ عند قيمة ثابتة
  4. استخدم VMMap أو مقلب كومة لفحص أيّ منطقة أو نوع نما
لماذا لا ينخفض Private Bytes بعد free أو GCيتغيّر Private Bytes بشكل مختلف بحسب ما إذا أعاد المخصِّص إلى نظام التشغيل منطقة لم يعد التطبيق يحتاجها، أو أبقاها لإعادة الاستخدامDecommit / Releaseيبقيها لإعادة الاستخدامالتطبيق يحرّر منطقة عبر free / GCهل يعيد المخصِّص المنطقة إلى نظام التشغيلينخفض Commit Chargeينخفض Private Bytesالمنطقة تبقى مُلتزَماً بهاPrivate Bytes يستقرّ مرتفعاًبرك، ذاكرات مؤقّتة، تجزئة

الشكل 6: صيرورة منطقة قابلة لإعادة الاستخدام داخل التطبيق ليست هي نفسها إعادة Commit إلى نظام التشغيل.

5.2. نمط مرشّح قويّ للتسريب

زيادة كالآتية، حيث يرتفع القاع درجةً مع كلّ جولة حمل في شكل «سلّم»، تستحقّ الانتباه.

Private Bytes
  ^
  |                    ________
  |             ______|
  |      ______|
  |_____|
  +----------------------------> تكرارات المعالجة نفسها

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

6. System Commit ── ما هو «Committed X/Y» فعليّاً

رقم «Committed X/Y» في تبويب [الأداء] ← [الذاكرة] في مدير المهام مؤشّر على مستوى النظام.

  • X: System Commit Charge ── الذاكرة المُلتزَم بها التي يعد Windows الآن بدعمها عبر النظام كلّه
  • Y: System Commit Limit ── سقف الـ Commit الذي يستطيع النظام تحمّله

يُحدَّد Commit Limit تقريباً بـ RAM الفيزيائيّة زائد مجموع كلّ ملفّات الصفحات. بلا ملفّ صفحات، يخرج أصغر قليلاً من RAM المثبَّتة.36

العلاقة بين System Commit Charge وCommit LimitCommit كلّ عمليّة والأقسام المشتركة والنواة يكوّن القيمة الحاليّة X، بينما تدعم RAM الفيزيائيّة وملفّ الصفحات السقف YX لا يمكن أن يتجاوز YPrivate Commit لكلّ عمليّةSystem Commit Charge - XCommit الأقسام المشتركة المغطّاة بملفّ الصفحاتCommit النواةRAM الفيزيائيّةSystem Commit Limit - Yملفّ الصفحات

الشكل 7: X هو الكمّيّة الموعودة الحاليّة وY هو السقف الذي يستطيع دعم ذلك الوعد ── وهذا ليس عرضاً لاستخدام ملفّ الصفحات.

يشمل System Commit Charge لا مجموع Private Bytes لكلّ عمليّة فحسب، بل أيضاً Commit الأقسام المشتركة المغطّاة بملفّ الصفحات وCommit الذي تستهلكه النواة. لذلك لا يستطيع مجموع Private Bytes لكلّ عمليّة وحده تفسير X بالكامل.

6.1. Commit Charge ليس استخدام ملفّ الصفحات

انظر نظاماً بـ 16GB من RAM وملفّ صفحات 16GB وCommitted عند 20/31GB.

تلك الـ 20GB لا تعني «كُتب 20GB إلى ملفّ الصفحات». إنّها الكمّيّة الكلّيّة التي يعد Windows بتوفير تغطية RAM أو ملفّ صفحات لها، متى دعت الحاجة، للصفحات الخاصّة القابلة للكتابة وما شابه.

في تلك اللحظة يمكن أن تجتمع الحالات الآتية:

  • معظمها مقيم في RAM
  • بعضها أُخرج إلى ملفّ الصفحات
  • بعضها مُلتزَم به لكن لم يُوصَل إليه أوّل مرّة بعد
  • بعضها مستهلَك Commitاً في جانب النواة

إن أردت رؤية استخدام ملفّ الصفحات الفعليّ، افحص Paging File(*)\% Usage منفصلاً عن Commit. وحتّى موادّ Microsoft نفسها توضّح أنّ ارتفاع استخدام ملفّ الصفحات وحده لا يدلّ بالضرورة على مشكلة أداء، وأنّه ينبغي الحكم مع بلوغ Commit Limit وقائمة Modified Page List وإدخال/إخراج الترحيل الفعليّ.6

6.2. ماذا يحدث عند الاقتراب من Commit Limit

عندما يصل System Commit Charge إلى Commit Limit، لا يمكن دعم طلبات الالتزام الجديدة. يؤدّي ذلك إلى فشل تخصيص ذاكرة العمليّات، وتعطّل التطبيقات، وصيرورة النظام غير مستجيب.3

هنا يهمّ X/Y للـ Commit أكثر من «RAM الحرّة». حتّى إن أجريت Trim لـ Working Set لتحرير RAM، فإنّ بلوغ Commit Limit لا يُحلّ ما لم ينخفض Commit Charge نفسه.

6.3. الأدوار الثلاثة لملفّ الصفحات

يخدم ملفّ الصفحات أساساً الأدوار الآتية.

  1. توسيع Commit Limit
  2. السماح بإخراج الصفحات المعدَّلة قليلة الاستخدام من RAM
  3. دعم مقلب أعطال النظام، بحسب الضبط

تعطيل ملفّ الصفحات ليس حالة بسيطة من «إدخال/إخراج القرص ينخفض دائماً والأمور تصير أسرع». إن صحّ شيء فهو أنّه يخفض Commit Limit، ويزيد احتمال بقاء صفحات معدَّلة لكن غير لازمة الآن في RAM، وقد يجعل التقاط المقلب الذي تحتاجه عند العطل مستحيلاً.36

لا يمكن تقرير حجم ملفّ الصفحات المناسب من RAM المثبَّتة وحدها. وتوضّح Microsoft نفسها أنّ ذلك لا يُعمَّم، لأنّ ذروة System Commit Charge ونوع مقلب الأعطال المطلوب يختلفان من نظام إلى نظام.6

7. تفصيل RAM الفيزيائيّة ── لا تحكم من انخفاض Available وحده

لا تُستخدم RAM الفيزيائيّة في Working Set لعمليّات المستخدم وحدها.

  • Working Set لكلّ عمليّة
  • ذاكرة التخزين المؤقّت لملفّات النظام
  • قوائم الصفحات مثل Standby وModified وFree وZeroed
  • Paged Pool / Nonpaged Pool للنواة
  • الذاكرة التي تحتفظ بها برامج تشغيل الأجهزة
  • مخزن ضغط الذاكرة
  • مناطق مشتركة مع وحدة المعالجة الرسوميّة وأجهزة أخرى أو محجوزة لها
  • الذاكرة المحجوزة عتاديّاً

7.1. Available يشمل ذاكرة مؤقّتة قابلة لإعادة الاستخدام أيضاً

Available MBytes في Windows ليس مجرّد RAM غير مستخدَمة بالكامل. إنّه مؤشّر يشمل، إلى جانب Free وZeroed، صفحات Standby التي يمكن إعادة استخدامها عند الحاجة.12

  • Free: صفحات غير مخصَّصة حاليّاً لأيّ غرض
  • Zeroed: صفحات صُفِّرت بحيث يمكن تسليمها بأمان لعمليّة أخرى
  • Standby: صفحات غادرت Working Set لكن محتواها ما زال مخزَّناً مؤقّتاً في RAM
  • Modified: صفحات تغيّر محتواها وتحتاج إلى الكتابة إلى التغطية المناسبة قبل إعادة الاستخدام
الحركة بين Working Set وقوائم الصفحاتيبيّن مغادرة الصفحات غير المتغيّرة إلى Standby والمعدَّلة إلى Modified، ثمّ إعادة الوصول والكتابة وإعادة الاستخدامإزالة صفحة غير متغيّرةإزالة صفحة معدَّلةاكتمال الكتابةإعادة وصولإعادة استخدام لغرض آخرتصفيروصول بعد التخصيصWorking Set - قيد الاستخدامStandby - مرشّح إعادة استخدام مع بقاء المحتوىModified - بانتظار الكتابةمخصَّصة لغرض آخرFree - غير مستخدَمةZeroed - متاحة لتخصيص جديدمضمَّنة في Available

الشكل 8: يشمل Available لا الذاكرة الحرّة بالكامل فحسب، بل أيضاً Standby القابلة لإعادة الاستخدام عند الحاجة.

«إلقاء كلّ الذاكرة المؤقّتة لزيادة RAM الحرّة» ليست دائماً ربحاً. إن كانت البيانات التي تحتاجها ما زالت جالسة في Standby، فإنّ إعادة الوصول يمكن أن تعيدها إلى Working Set بسرعة دون قراءة من القرص.

لذلك، حتّى إن كان Free منخفضاً في مدير المهام، إن كان Available وافراً ولم تكن أعطال الصفحات الصلبة أو انتظار القرص مسبّبة مشكلات، فقد يكون Windows ببساطة يستعمل RAM بفعاليّة ذاكرةً مؤقّتة.

7.2. عندما تنكمش RAM بلا عمليّة كبيرة

ليس نادراً أن يبقى استهلاك الذاكرة غير مفسَّر حتّى بعد جمع Private Working Set لكلّ عمليّة.

  • ذاكرة ملفّات مؤقّتة وملفّات معيَّنة في الذاكرة
  • Nonpaged Pool / Paged Pool
  • صفحات قفلها برنامج تشغيل
  • صفحات مشتركة
  • ضغط الذاكرة
  • تخصيصات مرتبطة بالافتراضيّة أو بوحدة المعالجة الرسوميّة

في هذه الحالة، بدل مواصلة التحديق في قائمة العمليّات، افحص Use Counts وProcesses وPriority Summary وFile Summary في RAMMap من Sysinternals. RAMMap هي الأداة الرسميّة لتفكيك الذاكرة الفيزيائيّة حسب الغرض وقائمة الصفحات والملفّ.13

إن استمرّ Nonpaged Pool وحده في النموّ، فتلك نقطة الشكّ في تسريب من جانب برنامج التشغيل أو النواة، لا في Private Bytes لتطبيق وضع المستخدم.

8. Page Fault ── العدد المرتفع ليس شاذاً بحدّ ذاته

يحدث Page Fault عندما تصل عمليّة إلى صفحة ليست حاليّاً في Working Set. رغم كلمة «Fault» في الاسم، فهذا ليس فشلاً استثنائيّاً ── بل الآليّة العاديّة التي تحرّك الذاكرة الافتراضيّة.1

8.1. أعطال الصفحات الليّنة

تُحلّ دون قراءة من القرص.

  • الصفحة ما زالت في Standby أو Transition
  • الصفحة المشتركة نفسها موجودة أصلاً في Working Set لعمليّة أخرى
  • الوصول أوّل مرّة إلى صفحة مُلتزَم بها وتعيين صفحة أصفار
  • القراءة المسبقة لمدير الذاكرة أدخلتها أصلاً إلى RAM

لذلك فإنّ \Memory\Page Faults/sec كبيراً لا يعني بالضرورة حدوث إدخال/إخراج قرص أو كمون.

8.2. أعطال الصفحات الصلبة

تتطلّب قراءة المحتوى من مخزن تغطية على القرص. والمصدر لا يقتصر على ملفّ الصفحات.

  • شيفرة وبيانات في .exe أو .dll
  • ملفّ معيَّن في الذاكرة
  • ملفّ الصفحات
التفرّع بين أعطال الصفحات الليّنة والصلبةعند الوصول إلى صفحة ليست في Working Set، تُعالَج عطلاً ليّناً إن لم يلزم إدخال/إخراج تخزين، أو عطلاً صلباً إن لزملا - Standby، مشتركة، demand-zero، إلخنعمالوصول إلى صفحة ليست في Working Setهل يلزم إدخال/إخراج تخزينعطل صفحة ليّنيدخل Working Set دون قراءة القرصعطل صفحة صلبمن أين تُقرأEXE / DLLملفّ معيَّن في الذاكرةملفّ الصفحاتيدخل Working Set بعد التحميل

الشكل 9: اسم «Page Fault» وحده لا يخبرك إن حدث إدخال/إخراج قرص.

تدرج Microsoft \Memory\Pages/sec و\Memory\Page Reads/sec و\Memory\Pages Input/sec بين العدّادات لقياس الأعطال الصلبة. وبما أنّ ارتفاعها لا يعني بالضرورة انخفاض الذاكرة، فاربطها بـ Available MBytes وكمون القرص ووقت الاستجابة الفعليّ.6

8.3. لا تضع عتبة شاملة واحدة

قيمة ثابتة مثل «أيّ شيء فوق 1000 Page Faults/sec شاذّ» يتغيّر معناها بحسب التخزين وحجم الصفحة وعبء العمل ومحلّيّة الوصول.

عمليّاً، صفّ الآتي على الخطّ الزمنيّ نفسه.

  • Memory\Available MBytes
  • Memory\Pages Input/sec
  • Memory\Page Reads/sec
  • كمون القراءة / Queue على القرص المستهدَف
  • Working Set وPrivate Bytes للعمليّة المستهدَفة
  • وقت معالجة التطبيق، والمهل، واستجابة واجهة المستخدم

إن انخفض Available في الوقت نفسه الذي يرتفع فيه الحمل، وارتفع Pages Input/sec وانتظار القرص، وتدهور وقت المعالجة أيضاً، فذلك يعطيك أساساً للشكّ في ترحيل سببه ضغط الذاكرة الفيزيائيّة.

9. أيّ شاشة أو أداة تُفحص ولأيّ غرض

ما تريد معرفته المؤشّر الذي يُفحص أوّلاً الأدوات الرئيسة
الكمّيّة التي تملكها العمليّة المستهدَفة الآن في RAM Working Set مدير المهام، Process Explorer، Get-Process
الجزء الخاصّ من ذلك ── RAM خاصّة بالعمليّة Private Working Set / Working Set - Private أعمدة التفاصيل في مدير المهام، Process Explorer، PerfMon
كمّيّة الـ Commit الخاصّة بالعمليّة المستهدَفة Private Bytes / Commit Size Process Explorer، PerfMon، VMMap، Get-Process
نطاق العناوين الافتراضيّ للعمليّة Virtual Bytes / Size Process Explorer، VMMap، Get-Process
هامش Commit النظام ككلّ Committed Bytes / Commit Limit مدير المهام [الأداء]، PerfMon
هامش إعادة استخدام RAM الفيزيائيّة Available MBytes مدير المهام، PerfMon
تفصيل Standby وModified وذاكرة الملفّات المؤقّتة قائمة الصفحات / تفصيل الغرض RAMMap
ما نما داخل Private Bytes Heap / Private Data / Managed Heap، إلخ VMMap، WinDbg، مقالب خاصّة ببيئة التشغيل
الترحيل الذي يشمل القرص Pages Input/sec، Page Reads/sec، كمون القرص PerfMon، WPR/WPA
اختيار أداة التحقيق في ذاكرة Windowsالأداة المستخدَمة تعتمد على ما إذا كان الهدف عمليّة واحدة أم النظام كلّه، ولحظة واحدة أم سلسلة زمنيّة، وما إذا لزم تتبّع الاحتفاظ داخل بيئة تشغيلنعمتفصيل لحظة واحدةسلسلة زمنيّةالنظام كلّهتفصيل RAM الفيزيائيّةخطّ زمنيّ يشمل CPU وI/O والانتظاركومة .NETكومة أصليّةما الذي تريد عزلههل الهدف عمليّة واحدةلحظة واحدة أم سلسلة زمنيّةVMMapPerfMon / PowerShellتفصيل RAM الفيزيائيّة أم خطّ زمنيّRAMMapWPR / WPAهل يلزم تتبّع الاحتفاظ داخل بيئة تشغيلdotnet-dump / PerfViewWinDbg / Application Verifier

الشكل 10: تقرير النطاق والخطّ الزمنيّ أوّلاً يتيح اختيار الأداة التي تحتاجها تماماً، لا أكثر ولا أقلّ.

9.1. مدير المهام

في مدير المهام، انظر إلى الشاشات منفصلة.

  • [العمليّات] أو [التفاصيل]: عائلة Working Set وعائلة Commit Size للعمليّات الفرديّة
  • [الأداء] ← [الذاكرة]: In use وAvailable وCommitted وCached وPaged pool وNon-paged pool على مستوى النظام

لا تحكم من العمود المسمّى «ذاكرة» وحده ── انقر بزرّ الفأرة الأيمن على عناوين الأعمدة في تبويب [التفاصيل] وأضف الأعمدة التي تحتاجها، مثل Working Set وPeak Working Set وCommit Size. تختلف أسماء الأعمدة بعض الشيء بحسب إصدار Windows ولغة العرض، لذا أكّد ما يعنيه العمود فعلاً قبل تسجيله.

9.2. التقاط سلسلة زمنيّة بـ PowerShell

إن عرفت معرّف العمليّة المستهدَفة، يمكنك التقاط اتّجاهات Working Set وPrivate Bytes وVirtual Bytes معاً بـ Get-Process.

param(
    [Parameter(Mandatory)]
    [int]$ProcessId,

    [int]$IntervalSeconds = 5,
    [int]$SampleCount = 60
)

$samples = for ($i = 0; $i -lt $SampleCount; $i++) {
    $process = Get-Process -Id $ProcessId -ErrorAction Stop

    [pscustomobject]@{
        Timestamp      = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
        ProcessId      = $process.Id
        WorkingSetMB   = [math]::Round($process.WorkingSet64 / 1MB, 1)
        PrivateBytesMB = [math]::Round($process.PrivateMemorySize64 / 1MB, 1)
        VirtualBytesMB = [math]::Round($process.VirtualMemorySize64 / 1MB, 1)
        Handles        = $process.HandleCount
        Threads        = $process.Threads.Count
    }

    Start-Sleep -Seconds $IntervalSeconds
}

$samples | Format-Table -AutoSize
$samples | Export-Csv .\memory-samples.csv -NoTypeInformation -Encoding utf8

Process.WorkingSet64 في .NET يقابل Working Set، وPrivateMemorySize64 يقابل Private Bytes، وVirtualMemorySize64 يقابل Virtual Bytes.141516

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

9.3. وضع النظام وعمليّة على الخطّ الزمنيّ نفسه بـ PerfMon

تسجيل الآتي على الأقلّ معاً يجعل العزل أسهل كثيراً.

\Process(<الهدف>)\ID Process
\Process(<الهدف>)\Working Set
\Process(<الهدف>)\Working Set - Private
\Process(<الهدف>)\Private Bytes
\Process(<الهدف>)\Virtual Bytes

\Memory\Available MBytes
\Memory\Committed Bytes
\Memory\Commit Limit
\Memory\Pages Input/sec
\Memory\Page Reads/sec
\Memory\Pool Nonpaged Bytes
\Memory\Pool Paged Bytes

عندما تشترك عدّة عمليّات في الاسم نفسه، أو يحدث إعادة تشغيل أثناء المراقبة، لا يستطيع اسم النسخة وحده ── Process(name) أو Process(name#N) ── تثبيت الهدف. سجّل ID Process لكلّ عيّنة أيضاً، واعتمد فقط النسخة التي تطابق قيمتها المعرّف الذي تتابعه. وعند عبور إعادة تشغيل تغيّر المعرّف، سجّل وقت التبديل على حدة أيضاً.

قد تُترجَم أسماء عدّادات أداء Windows بحسب لغة العرض. إن فشل تحديد الاسم الإنجليزيّ مباشرة في PowerShell في إيجاده، فأضف العدّاد عبر واجهة PerfMon الرسوميّة، أو افحص الأسماء في بيئتك المحلّيّة بـ Get-Counter -ListSet *.

9.4. لا تخلط أدوار VMMap وRAMMap

  • VMMap: يفكّك الذاكرة الافتراضيّة وWorking Set لعمليّة واحدة إلى Heap وImage وMapped File وPrivate Data وManaged Heap وما شابه
  • RAMMap: يفكّك RAM الفيزيائيّة للنظام كلّه حسب الغرض وقائمة الصفحات والعمليّة والملفّ

«ما الذي جعل Private Bytes لهذه العمليّة ينمو» مهمّة VMMap؛ و«ما الغرض الذي تُستخدم له RAM التي لا تفسّرها قائمة العمليّات» مهمّة RAMMap.1713

10. قراءة الأعراض من تركيبات الأرقام

النمط المرصود الفرضيّة الأولى ما يُفحص بعد ذلك
Working Set يرتفع، Private Bytes مستقرّ أوّل وصول إلى صفحات موجودة، DLL مشتركة، ملفّ معيَّن، ذاكرة ملفّات مؤقّتة Image / Mapped File في VMMap، Pages Input/sec
Private Bytes يرتفع، Working Set مستقرّ نما Private Commit لكنّه غير مقيم أو أُجري له Trim Heap / Private Data / Managed Heap في VMMap
كلاهما يرتفع بعد البدء مباشرة ثمّ يستوي JIT، ذاكرة مؤقّتة، بركة، تسخين التهيئة ما إذا نما مرّة أخرى تحت الحمل الإضافيّ نفسه
قاع Private Bytes يرتفع مع كلّ جولة حمل تسريب، أو ذاكرة مؤقّتة بلا سقف، أو مخصِّص يحتفظ بالذاكرة بعد التحرير لقطات VMMap قبل وبعد، مقلب كومة
Working Set وحده يهبط فجأة ويعود مع النشاط نظام التشغيل أو التطبيق أجرى Trim لـ Working Set Private Bytes، Pages Input/sec، وقت الاستجابة
X في Committed X/Y يقترب من Y ضغط Commit على مستوى النظام أكبر مستهلكي Private Bytes، Paged/Nonpaged Pool، إعدادات ملفّ الصفحات
Available منخفض، وPages Input/sec وكمون القرص مرتفعان ضغط RAM فيزيائيّ وترحيل صلب أكبر مستهلكي Working Set، RAMMap، ارتباط عبء العمل
استخدام RAM مرتفع لكن لا عمليّة كبيرة ذاكرة مؤقّتة، صفحات مشتركة، برك النواة، برامج تشغيل، ضغط، إلخ RAMMap، Pool Nonpaged/Paged Bytes
RAM حرّة متاحة، ومع ذلك يفشل تطبيق 32-بت وحده سقف مساحة عناوين افتراضيّة أو تجزئة Free/Reserved في VMMap، إعداد LAA للملفّ التنفيذيّ
Private Bytes مرتفع لكن لا ينمو مع تكرار المعالجة بركة أو ذاكرة مؤقّتة ربّما تحتفظ بعلامة مائيّة عالية حدّها، سلوك إعادة الاستخدام، الاستقرار بعد الذروة

أهمّ شيء في هذا الجدول هو قراءته تركيباً، لا من قيمة واحدة وحدها.

11. إجراء عمليّ للتحقيق في تسريب ذاكرة

11.1. قرّر أوّلاً شروط إعادة الإنتاج ونقطة الاستقرار

«ينمو على مدى أيّام قليلة» وحده لا يمكن مقارنته.

  • مقدار تسخين ما بعد البدء الذي يُضمَّن
  • ممّ يتألّف دورة تشغيل واحدة
  • كم ثانية تُنتظَر بعد دورة واحدة
  • كم جولة تلزم لبلوغ سقف الذاكرة المؤقّتة
  • ما إذا أمكن استخدام الدخل نفسه للبناء السليم والإشكاليّ

قرّر هذا كلّه.

11.2. سجّل العمليّة والنظام في آن واحد

على الأقلّ، أبقِ الآتي مسجَّلاً في الأختام الزمنيّة نفسها.

  • Working Set للهدف
  • Private Bytes للهدف
  • Virtual Bytes للهدف
  • Committed Bytes / Commit Limit للنظام
  • Available MBytes
  • Pages Input/sec
  • عدد المقابض، عدد الخيوط
  • عدد العمليّات أو العناصر المعالجة

إن كان Private Bytes للعمليّة مستقرّاً بينما يواصل Commit النظام النموّ، يلزم توسيع النطاق إلى عمليّات أخرى والنواة وبرامج التشغيل والأقسام المشتركة.

11.3. قرّر أوّلاً أيّ «بُعد» ينمو

  • Working Set وحده: صفحات مقيمة، مشتركة أو مشتقّة من ملفّ، Trim وإعادة تحميل
  • Private Bytes: Commit خاصّ بالعمليّة
  • Virtual Bytes وحده: Reserve، تعيين، تجزئة مساحة العناوين
  • System Commit وحده: بما فيه عمليّات أخرى وجانب النواة
  • Nonpaged Pool: جانب برنامج التشغيل/النواة
  • Handles / GDI / USER: تسريبات في موارد غير الذاكرة

تجاوز هذا الترتيب والقفر مباشرة إلى أخذ مقلب ينتهي بقراءة جبل من المعلومات بينما الهدف خاطئ.

11.4. انتقل إلى التفصيل

  • عمليّة أصليّة: VMMap، WinDbg، Application Verifier، تتبّع الكومة
  • .NET: dotnet-counters، dotnet-gcdump، dotnet-dump، PerfView
  • على مستوى النظام: RAMMap، PerfMon، WPR/WPA
  • بركة النواة: PoolMon، WinDbg

يعرض VMMap الذاكرة الافتراضيّة المُلتزَم بها للعمليّة، وWorking Set المخصَّص لكلّ جزء منها، مفصَّلاً حسب النوع. مدى تضييق نموّ Private Bytes إلى Heap أو Private Data أو Managed Heap أو Mapped File يغيّر كثيراً كلفة التحقيق الذي يلي.17

11.5. بعد الإصلاح، قارن الاتّجاه تحت الشروط نفسها

لا يكفي اختلاف قيمة الذروة قبل الإصلاح وبعده. إن اختلفت قيمة البداية، يمكن أن تنقلب المقارنة بسهولة.

  • حالة بدء واحدة
  • دخل واحد
  • العدد نفسه من العمليّات
  • وقت الانتظار نفسه
  • فاصل العيّنات نفسه

── وقارن قيمة القاع والاتّجاه بعد كلّ دورة. إثبات إصلاح التسريب ليس «أنّ الحدّ الأقصى صار أصغر»، بل أنّ النموّ يتقارب الآن حتّى عند تكرار الحمل نفسه.

12. إعادة صياغة المفاهيم الخاطئة الشائعة

المفهوم الخاطئ 1: ذاكرة مدير المهام تساوي الكمّيّة الكلّيّة التي خصّصها التطبيق

إعادة الصياغة: افحص أيّ عمود هو. لعائلة Working Set هي الكمّيّة المقيمة حاليّاً في RAM؛ لعائلة Commit Size هي الـ Commit الخاصّ بتلك العمليّة.

المفهوم الخاطئ 2: Private Bytes يساوي بايتات على ملفّ الصفحات

إعادة الصياغة: Private Bytes هو Commit Charge خاصّ. إنّه كمّيّة موعودة منطقيّة تشمل الصفحات الموجودة الآن في RAM والصفحات التي ستغطّى بملفّ الصفحات إذا دعت الحاجة ومتى دعت.

المفهوم الخاطئ 3: Commit X/Y يساوي استخدام ملفّ الصفحات / سعة ملفّ الصفحات

إعادة الصياغة: X هو Commit Charge على مستوى النظام، وY هو Commit Limit. ملفّ الصفحات يوسّع Y، لكن X لا يترجم مباشرة إلى استخدام على القرص.

المفهوم الخاطئ 4: ارتفاع Page Faults/sec يعني تبديلاً إلى القرص

إعادة الصياغة: يشمل هذا الأعطال الليّنة أيضاً. افحص Pages Input/sec وPage Reads/sec وكمون القرص لترى إن كان إدخال/إخراج القرص متورّطاً فعلاً.

المفهوم الخاطئ 5: انخفاض Free RAM يعني نقص الذاكرة

إعادة الصياغة: انظر إلى Available وStandby والترحيل الصلب ووقت الاستجابة. ملء RAM بذاكرة مؤقّتة قابلة لإعادة الاستخدام أمر عاديّ.

المفهوم الخاطئ 6: تقليص Working Set يعني إصلاح تسريب ذاكرة

إعادة الصياغة: ربّما طردت صفحات من RAM فحسب. افحص ما إذا انخفض Private Bytes وما يُحتفَظ به داخل الكومة فعلاً.

المفهوم الخاطئ 7: زيادة Private Bytes تؤكّد تسريباً

إعادة الصياغة: لا يمكن الحكم إلا بعد فحص ما إذا تقارب عند تكرار عبء العمل نفسه، وأيّ نوع من الذاكرة نما، وما إذا كانت ذاكرة مؤقّتة قابلة للتحرير.

13. الخلاصة

  • «استخدام الذاكرة» في Windows ليس رقماً واحداً. فكّر في مساحة العناوين والـ Commit وإقامة RAM وقابليّة المشاركة كلّاً على حدة.
  • Working Set هو الصفحات الموجودة الآن في RAM، بما فيها Private وShared. وPrivate Working Set هو الصفحات الخاصّة بالعمليّة المقيمة ضمن ذلك.
  • Private Bytes هو Commit Charge خاصّ بالعمليّة؛ ليس الكمّيّة الموجودة الآن في RAM ولا الكمّيّة المكتوبة فعليّاً إلى ملفّ الصفحات.
  • Committed X/Y هو Commit Charge / Commit Limit على مستوى النظام. ملفّ الصفحات يدعم أساساً Commit Limit وإخلاء الصفحات المعدَّلة ومقالب الأعطال.
  • عنوان افتراضيّ Reserved، وصفحة Committed، وصفحة لُمست فعلاً ودخلت Working Set مراحل منفصلة.
  • Page Fault تشغيل عاديّ، والعطل الليّن لا يقرأ من القرص. والأعطال الصلبة أيضاً يمكن أن تحدث لا من ملفّ الصفحات فحسب بل من EXE أو DLL أو ملفّ معيَّن.
  • يُثبَت تسريب الذاكرة لا بحجمه في لحظة واحدة، بل بقيمة القاع والاتّجاه بعد الحمل نفسه، مع التفصيل.
  • المسار الأساسيّ: VMMap لتفصيل عمليّة فرديّة، وRAMMap لـ RAM الفيزيائيّة على مستوى النظام، وPerfMon لسلسلة زمنيّة، وأداة مقلب مخصَّصة لما يحدث داخل بيئة تشغيل.

في المرّة التالية التي تلاحظ فيها في مدير المهام أنّ «الذاكرة تنمو»، ابدأ بسؤال نفسك هذا.

ما الذي ينمو: Working Set، أم Private Bytes، أم Virtual Bytes، أم System Commit؟

هذا السؤال وحده يجعل مدخل تحقيقك أدقّ بكثير.

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

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

تتعامل شركة كومورا سوفت ذ.م.م. مع تحقيقات السبب الجذريّ التي تجمع PerfMon وVMMap وRAMMap وWinDbg وأدوات تشخيص .NET لتزايد ذاكرة تطبيقات Windows، وتدهور الأداء بعد التشغيل الطويل، وOutOfMemory في عمليّات 32-بت، ونقص الذاكرة الذي يحدث فقط في بيئة الزبون. لا نتوقّف عند مجرّد «الذاكرة مرتفعة» ── نعزل أيّ منطقة نمت، عبر أيّ عمليّة، ولماذا، ومن أين تُرجَع أو تُحتفَظ.

روابط مرجعيّة

  1. Microsoft Learn, Working Set. حول كون Working Set للعمليّة مجموعة الصفحات المقيمة حاليّاً في الذاكرة الفيزيائيّة، بما فيها الصفحات المشتركة؛ والفرق بين أعطال الصفحات الليّنة والصلبة؛ وصفحات Transition؛ وإزالة الصفحات من Working Set.  2 3 4 5

  2. Microsoft Learn, PROCESS_MEMORY_COUNTERS_EX2 structure. حول تعريفات WorkingSetSize وPrivateWorkingSetSize وPrivateUsage وSharedCommitUsage، وحول تمثيل PagefileUsage وPrivateUsage كليهما Commit Charge للعمليّة.  2 3 4

  3. Microsoft Learn, Introduction to page files. حول دعم ملفّ الصفحات إخلاء الصفحات المعدَّلة ومقالب أعطال النظام وتوسيع System Commit Limit؛ وتعريفات System Commit Charge وCommit Limit؛ وكيفيّة قياسهما عبر مدير المهام وعدّادات الأداء.  2 3 4

  4. Microsoft Learn, Page State. حول حالات Free وReserved وCommitted للصفحة الافتراضيّة، وحول كون الصفحات Reserved بلا تخزين فيزيائيّ مرتبط بها وغير قابلة للوصول.  2

  5. Microsoft Learn, VirtualAlloc function. حول الفرق بين MEM_RESERVE وMEM_COMMIT؛ وحول احتساب الالتزام على ذاكرة النظام كلّه وملفّ الصفحات؛ وحول إمكان عدم تخصيص الصفحة الفيزيائيّة الفعليّة حتّى أوّل وصول.  2 3

  6. Microsoft Learn, How to determine the appropriate page file size for 64-bit versions of Windows. حول اعتماد حجم ملفّ الصفحات على ذروة Commit Charge ومتطلّبات مقلب الأعطال؛ وحول قراءة الأعطال الصلبة لا من ملفّ الصفحات فحسب بل أيضاً من EXE وDLL والملفّات المعيَّنة في الذاكرة؛ والعدّادات ذات الصلة.  2 3 4 5 6

  7. Microsoft Learn, Virtual Address Space. حول امتلاك كلّ عمليّة مساحة عناوين افتراضيّة مستقلّة وجدول صفحات، وحول كون العنوان الافتراضيّ ليس عنواناً فيزيائيّاً بحدّ ذاته. 

  8. Microsoft Learn, Memory Limits for Windows and Windows Server Releases. حول كون مساحة العناوين الافتراضيّة لعمليّة 32-بت في وضع المستخدم 2GB عادةً، وصيرورتها 2GB أو 4GB على Windows 64-بت بحسب IMAGE_FILE_LARGE_ADDRESS_AWARE. 

  9. Microsoft Learn, SetProcessWorkingSetSize function. حول كون قيمتَي Working Set الدنيا والعليا لا تضمنان الإقامة؛ وإمكان إفراغ Working Set؛ وإمكان تدهور أداء النظام بإعدادات أو عمليّات مفرطة. 

  10. Microsoft Learn, Memory Performance Information. حول التقابل بين عدّادات أداء Windows وواجهات إدارة الذاكرة وعرض مدير المهام، بما فيه Working Set / Working Set - Private / Private Bytes لكائن Process، وCommitted Bytes / Commit Limit لكائن System. 

  11. Microsoft Learn, MapViewOfFile function. حول جعل FILE_MAP_COPY كلّ صفحة قابلة للنسخ عند الكتابة، لذا يُحجز Commit Charge للعرض كلّه ليُغطَّى بملفّ الصفحات عند التعيين. 

  12. Microsoft Learn, Understanding Node Metrics and Properties in HPC Cluster Manager. حول حساب Available Physical Memory مجموعاً لقوائم Zeroed وFree وStandby، وحول معنى كلّ من قوائم الصفحات تلك. 

  13. Microsoft Sysinternals, RAMMap. حول تحليل استخدام الذاكرة الفيزيائيّة في Windows حسب الغرض وقائمة الصفحات والعمليّة والأولويّة والصفحة الفيزيائيّة والملفّ.  2

  14. Microsoft Learn, Process.WorkingSet64 Property. حول إرجاع WorkingSet64 لـ Working Set للعمليّة بالبايت، مقابل عدّاد أداء Working Set لكائن Process. 

  15. Microsoft Learn, Process.PrivateMemorySize64 Property. حول إرجاع PrivateMemorySize64 للذاكرة الخاصّة بالعمليّة التي لا يمكن مشاركتها مع عمليّات أخرى، مقابل عدّاد أداء Private Bytes. 

  16. Microsoft Learn, Process.VirtualMemorySize64 Property. حول إرجاع VirtualMemorySize64 لكمّيّة الذاكرة الافتراضيّة المخصَّصة للعمليّة، مقابل عدّاد أداء Virtual Bytes. 

  17. Microsoft Sysinternals, VMMap. حول تفكيك الذاكرة الافتراضيّة المُلتزَم بها لعمليّة حسب النوع، وعرض الذاكرة الفيزيائيّة(Working Set)المخصَّصة لكلّ منها، مع خريطة ذاكرة مفصَّلة.  2

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

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

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

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

هل عمود «الذاكرة» في مدير المهام يعرض إجمالي الذاكرة التي خصّصها التطبيق؟
لا. لمدير المهام عدّة أعمدة للذاكرة ── عائلة Working Set، وعائلة Private Working Set، وCommit Size، وغيرها ── ويتغيّر المعنى بحسب الشاشة والعمود الذي تنظر إليه. Working Set هو الصفحات المقيمة حاليّاً في RAM؛ وPrivate Bytes أو Commit Size هو كمّيّة الـ Commit الخاصّة بتلك العمليّة. لا تقرأ عمود «الذاكرة» الواحد على أنّه السعة الكلّيّة التي خصّصها التطبيق، ولا على أنّه حجم تسريب.
ما الفرق بين Working Set وPrivate Bytes؟
Working Set هو كمّيّة الصفحات المرئيّة لتلك العمليّة والمقيمة حاليّاً في RAM الفيزيائيّة، بما فيها الصفحات القابلة للمشاركة مثل شيفرة DLL وملفّات معيَّنة في الذاكرة. Private Bytes هو كمّيّة الذاكرة المُلتزَم بها والمستخدَمة حصراً من تلك العمليّة، سواء أكانت مقيمة في RAM أم لا. لذلك لا يتساويان أبداً، ولا يكون أحدهما أكبر من الآخر على نحو ثابت.
هل «Committed 18/32GB» في مدير المهام يعني أنّ 18GB كُتبت إلى ملفّ الصفحات؟
لا. الرقم الأيسر هو إجمالي الـ Commit الذي يعد النظام كلّه الآن بدعمه؛ والرقم الأيمن هو سقف الـ Commit الذي يستطيع النظام تحمّله. يُحدَّد السقف تقريباً بمجموع RAM وملفّ الصفحات، لكن ليس كلّ الإجمالي الأيسر جالساً فعليّاً في ملفّ الصفحات. معظم الصفحات المُلتزَم بها في RAM، وبعض الصفحات المُلتزَم بها لم تُعيَّن لها صفحة فيزيائيّة قطّ. في المقابل، الصفحات التي يمكن إعادة تحميلها من ملفّها الأصليّ ── مثل EXE وDLL والملفّات المعيَّنة في الذاكرة ── لا ترفع بالضرورة الـ Commit الخاصّ بنفس القدر الذي ترفع به Working Set.
هل يمكن أن يحدث OutOfMemory رغم توفّر RAM حرّة؟
نعم. قد يفشل التخصيص لأسباب غير RAM الفيزيائيّة، منها نفاد مساحة العناوين الافتراضيّة لعمليّة 32-بت، أو نقص نطاق عناوين حرّ متواصل، أو سقف Commit النظام، أو حدود خاصّة بـ Job Object أو بيئة التشغيل. وعلى وجه الخصوص، عمليّة 32-بت على Windows 64-بت تُحدَّ عادةً بـ 2GB من مساحة العناوين الافتراضيّة في وضع المستخدم ما لم تكن Large Address Aware.
هل تعطيل ملفّ الصفحات يجعل Windows أسرع؟
لا يمكن افتراض ذلك قاعدةً عامّة. تعطيل ملفّ الصفحات يخفض سقف Commit النظام، ويصعّب إخلاء الصفحات المعدَّلة غير المستخدَمة من RAM، ويؤثّر في كيفيّة ضبط مقالب الأعطال. ينبغي تقرير حجم ملفّ الصفحات بقياس ذروة Commit Charge ومقلب الأعطال الذي تحتاجه ── وليس إعداداً يُعطَّل بلا مبرّر.
هل ارتفاع Page Faults/sec يعني أنّ النظام قصير الذاكرة؟
لا يمكن الجزم من ذلك وحده. تشمل أعطال الصفحات أعطالاً ليّنة تُحلّ من صفحات Standby في RAM أو صفحات مشتركة مع عمليّة أخرى، وأعطالاً صلبة تقرأ من القرص. بدل النظر إلى Page Faults/sec بمعزل، افحص Pages Input/sec وPage Reads/sec وAvailable MBytes وكمون القرص ووقت المعالجة معاً على الخطّ الزمنيّ نفسه.

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

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

غو كومورا

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

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

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