מה באמת אומר "שימוש בזיכרון" של 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 אינו בהכרח אומר קלט/פלט דיסק. יש soft fault, שאפשר לפתור בתוך ה-RAM, ו-hard fault שקוראים מקובץ הדפדוף, מקובצי הרצה, מקבצים שממופים לזיכרון וכדומה.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 לא כעל “פס אחד” אלא לאורך ארבעה צירים.

ארבעה צירים עצמאיים לסיווג דף אחדבדקו בנפרד את מצב הכתובת הווירטואלית, את הגיבוי של דפים committed, את השהייה ב-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
פרטי לתהליך, committed, מתגורר ב-RAM כלול כלול כלול כלול
פרטי לתהליך, committed, אינו מתגורר ב-RAM אינו כלול אינו כלול כלול כלול
דף משותף של DLL או קובץ ממופה, מתגורר ב-RAM כלול בדרך כלל אינו כלול בדרך כלל אינו כלול כלול
Reserved אך לא committed אינו כלול אינו כלול אינו כלול עשוי להיכלל
טווח כתובות שאינו בשימוש אינו כלול אינו כלול אינו כלול בדרך כלל אינו כלול
מיפוי סוגי דפים למדדי הזיכרון העיקרייםמראה אילו מדדים כוללים דפים פרטיים מתגוררים, דפים פרטיים שאינם מתגוררים, דפים משותפים מתגוררים, וטווחים שמורים בלבדPrivate, committed, מתגורר ב-RAMPrivate, committed, אינו מתגורר ב-RAMדף משותף, מתגורר ב-RAMReserved, לא committedWorking 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 זה נספר ל-Commit Charge של המערכת, אבל הדף הפיזי בפועל עשוי לא להיות מוקצה עד הגישה הראשונה. דף שנוגעים בו בפעם הראשונה מאותחל באפסים, עובר demand-zero fault, ונכנס ל-Working Set.51

לכן, אף על פי שקוראים לזה “הוקצה” בשני המקרים, בפועל יש שלושת השלבים הבאים.

שלושה שלבים מ-Reserve דרך Commit לשהייה ב-RAMמראה את הזרימה של שמירת כתובת וירטואלית, commit של הדף, והקצאת דף פיזי בגישה הראשונה עם כניסה ל-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 ונתונים לקריאה בלבד
  • קבצים שממופים לזיכרון
  • זיכרון משותף
  • דפים שהפכו פרטיים לאותו תהליך אחרי copy-on-write
  • דפים שסביבת הריצה וספריות שונות נגעו בהם

4.1. Working Set שגדל אינו בהכרח אומר שהוקצה יותר

גישה בפעם הראשונה לדף שכבר היה committed יכולה להגדיל את ה-Working Set לבדו בזמן ש-Private Bytes נשאר ללא שינוי. באותו אופן, כשקובץ גדול ממופה לזיכרון ונקרא ברצף, דפים מגובים בקובץ נכנסים ל-Working Set בזמן ש-Private Bytes כמעט אינו גדל.

ולהפך, כש-Windows עושה Trim ל-Working Set בתגובה ללחץ זיכרון, ה-Working Set לבדו מצטמק בזמן שהאפליקציה מחזיקה לוגית את אותו זיכרון. נגיעה חוזרת אחר כך מחזירה אותו דרך Page Fault.

לכן ירידה ב-Working Set אינה בהכרח אומרת “האפליקציה שחררה”, ועלייה אינה בהכרח אומרת “האפליקציה הקצתה מחדש”.

זרימה טיפוסית שבה רק ה-Working Set עולה ויורדאותו דף committed נכנס ל-RAM בגישה הראשונה, הופך ללא-מתגורר ב-Trim, וחוזר בגישה חוזרת, בזמן ש-Private Bytes ממשיך להיספרגישה ראשונהTrim תחת לחץ זיכרוןPage Fault בגישה חוזרתאותו דף committedמתגורר ב-RAMאינו מתגוררכלול ב-Working Setאינו כלול ב-Working Setנספר ב-Private Bytes כל עוד committed

איור 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 הוא כמות הזיכרון הווירטואלי ש-committed באופן בלעדי לאותו תהליך. הוא מייצג 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 של ערימת ה-native שמשמשים HeapAlloc, malloc, new ודומיהם
  • Private Data ש-committed ישירות עם VirtualAlloc
  • האזור ה-committed של ערימת ה-GC של .NET
  • החלק ממחסנית חוט ש-committed בפועל
  • ה-Commit Charge לכל התצוגה שנשמר כשממפים תצוגת copy-on-write(FILE_MAP_COPY
  • מאגרים פרטיים שספריות ו-SDK של התקנים מחזיקים בפנים

בתצוגת copy-on-write שנוצרת עם 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 או ב-dump של ערימה כדי לבדוק איזה אזור או סוג גדל
למה Private Bytes אינו יורד אחרי free או GCPrivate Bytes משתנה אחרת בהתאם לשאלה אם המקצה מחזיר למערכת ההפעלה אזור שהאפליקציה כבר אינה צריכה, או מחזיק אותו לשימוש חוזרDecommit / Releaseמחזיק לשימוש חוזרהאפליקציה משחררת אזור דרך free / GCהאם המקצה מחזיר אותו למערכת ההפעלהCommit Charge יורדPrivate Bytes יורדהאזור נשאר committedPrivate Bytes נשאר גבוהמאגרים, מטמונים, פיצול

איור 6: אזור שהפך ניתן לשימוש חוזר בתוך האפליקציה אינו אותו דבר כמו החזרת ה-Commit שלו למערכת ההפעלה.

5.2. תבנית מועמדת חזקה לדליפה

עלייה כמו הבאה, שבה הרצפה עולה במדרגות עם כל סבב עומס, ראויה לתשומת לב.

Private Bytes
  ^
  |                    ________
  |             ______|
  |      ______|
  |_____|
  +----------------------------> חזרות על אותו עיבוד

עם זאת, גם צורת מדרגות יכולה להיות רק כמה סבבי צמיחה מ-JIT בפעם הראשונה, גופנים, מפענחי תמונות, מאגרי חיבור או חימום מטמון, ואחריהם היא מתייצבת. מה שחשוב אינו שהיא גדלה, אלא שהיא נכשלת להתכנס למצב יציב.

6. System Commit — מה באמת “Committed X/Y”

הנתון “Committed X/Y” בלשונית [ביצועים] ← [זיכרון] של מנהל המשימות הוא מדד ברמת המערכת.

  • X: System Commit Charge — הזיכרון ה-committed ש-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
  • חלקו פונה לקובץ הדפדוף
  • חלקו committed אבל עדיין לא הייתה לו גישה ראשונה
  • חלקו נצרך כ-Commit מצד הליבה

אם אתם רוצים לראות שימוש בפועל בקובץ הדפדוף, בדקו Paging File(*)\% Usage בנפרד מ-Commit. גם החומר של Microsoft עצמה מסביר ששימוש גבוה בקובץ הדפדוף לבדו אינו בהכרח מעיד על בעיית ביצועים, ושצריך לשפוט אותו יחד עם הגעה ל-Commit Limit, עם Modified Page List ועם קלט/פלט דפדוף בפועל.6

6.2. מה קורה כשמתקרבים ל-Commit Limit

כש-System Commit Charge מגיע ל-Commit Limit, אי אפשר לגבות בקשות commit חדשות. זה מוביל לכישלונות הקצאת זיכרון של תהליכים, לקריסות אפליקציות ולמערכת שאינה מגיבה.3

כאן X/Y של Commit חשוב יותר מ”RAM פנוי”. גם אם תעשו Trim ל-Working Set כדי לפנות RAM, הגעה ל-Commit Limit אינה נפתרת אלא אם ה-Commit Charge עצמו יורד.

6.3. שלושת התפקידים של קובץ הדפדוף

קובץ הדפדוף משרת בעיקר את התפקידים הבאים.

  1. הרחבת ה-Commit Limit
  2. לאפשר לפנות מ-RAM דפים שהשתנו ונמצאים בשימוש נדיר
  3. לגבות את dump הקריסה של המערכת, בהתאם להגדרה

השבתת קובץ הדפדוף אינה מקרה פשוט של “קלט/פלט דיסק תמיד יורד והדברים נעשים מהירים יותר”. אם כבר, היא מורידה את ה-Commit Limit, מגדילה את הסיכוי שדפים שהשתנו אבל כרגע אינם נחוצים יישארו ב-RAM, ויכולה להפוך לבלתי אפשרי לתפוס את ה-dump שאתם צריכים כשקריסה מתרחשת.36

את גודל קובץ הדפדוף המתאים אי אפשר להחליט לפי ה-RAM המותקן לבדו. Microsoft עצמה מסבירה שאי אפשר להכליל, כי שיא ה-System Commit Charge וסוג dump הקריסה הנדרש שונים ממערכת למערכת.6

7. פירוט ה-RAM הפיזי — אל תשפטו מ-Available נמוך לבדו

RAM פיזי אינו משמש רק את ה-Working Set של תהליכי משתמש.

  • ה-Working Set של כל תהליך
  • מטמון קובצי המערכת
  • רשימות דפים כמו Standby, Modified, Free ו-Zeroed
  • Paged Pool / Nonpaged Pool של הליבה
  • זיכרון שמחזיקים מנהלי התקנים
  • מחסן דחיסת הזיכרון
  • אזורים משותפים עם ה-GPU והתקנים אחרים או שמורים להם
  • זיכרון ששמור לחומרה

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
  • דפים שנעלו על ידי מנהל התקן
  • דפים משותפים
  • דחיסת זיכרון
  • הקצאות הקשורות לווירטואליזציה או ל-GPU

במקרה כזה, במקום להמשיך לבהות ברשימת התהליכים, בדקו 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. Soft page fault

אלה נפתרים בלי לקרוא מהדיסק.

  • הדף עדיין ב-Standby או ב-Transition
  • אותו דף משותף כבר נמצא ב-Working Set של תהליך אחר
  • ניגשים בפעם הראשונה לדף committed ומוקצה דף אפסים
  • הקריאה מראש של מנהל הזיכרון כבר הכניסה אותו ל-RAM

לכן \Memory\Page Faults/sec גדול אינו בהכרח אומר שמתרחש קלט/פלט דיסק או השהיה.

8.2. Hard page fault

אלה דורשים לקרוא תוכן ממאגר גיבוי בדיסק. המקור אינו מוגבל לקובץ הדפדוף.

  • קוד ונתונים ב-.exe או ב-.dll
  • קובץ שממופה לזיכרון
  • קובץ הדפדוף
הענף בין soft page fault ל-hard page faultבגישה לדף שאינו ב-Working Set, מטפלים כ-soft page fault אם אין צורך בקלט/פלט אחסון, או כ-hard page fault אם ישלא - Standby, משותף, demand-zero וכוכןגישה לדף שאינו ב-Working Setהאם נדרש קלט/פלט אחסוןSoft page faultנכנס ל-Working Set בלי קריאת דיסקHard page faultמאיפה קוראיםEXE / DLLקובץ שממופה לזיכרוןקובץ דפדוףנכנס ל-Working Set אחרי טעינה

איור 9: השם “Page Fault” לבדו אינו יכול לומר לכם אם התרחש קלט/פלט דיסק.

Microsoft מונה את \Memory\Pages/sec, \Memory\Page Reads/sec ו-\Memory\Pages Input/sec בין המונים למדידת hard fault. מכיוון שגובהם אינו בהכרח אומר שחסר זיכרון, קשרו אותם ל-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, dump ייעודי לסביבת ריצה
דפדוף שמערב דיסק Pages Input/sec, Page Reads/sec, השהיית דיסק PerfMon, WPR/WPA
בחירת כלי חקירת זיכרון של Windowsהכלי לשימוש תלוי בשאלה אם היעד הוא תהליך אחד או כל המערכת, נקודה אחת בזמן או סדרת זמן, ואם צריך לעקוב אחרי החזקה בתוך סביבת ריצהכןפירוט של נקודה אחתסדרת זמןכל המערכתפירוט RAM פיזיציר זמן כולל מעבד, קלט/פלט והמתנותערימת .NETערימת nativeמה אתם רוצים לבודדהאם היעד הוא תהליך אחדנקודה אחת או סדרת זמן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

לאפליקציה עם כמה מופעים, עקבו לפי PID ולא לפי שם. לניטור ארוך טווח שבו הפעלה מחדש משנה את ה-PID, תכננו את האיסוף כך שיירשם זמן ההתחלה, שם השירות וכדומה, כדי שהיעד לעולם לא יוחלף בטעות.

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 לכל דגימה, ואמצו רק את המופע שערכו תואם ל-PID שאתם עוקבים אחריו. כשאתם חוצים הפעלה מחדש שמשנה את ה-PID, רשמו בנפרד גם את זמן המעבר.

שמות מוני הביצועים של 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 יציב Commit פרטי גדל אבל אינו מתגורר או עבר Trim Heap / Private Data / Managed Heap של VMMap
שניהם עולים מיד אחרי ההפעלה, ואז מתיישרים JIT, מטמון, מאגר, חימום אתחול האם זה גדל שוב תחת אותו עומס נוסף
רצפת Private Bytes עולה עם כל סבב עומס דליפה, מטמון בלי תקרה, או מקצה שמחזיק זיכרון אחרי שחרור צילומי VMMap לפני ואחרי, dump של ערימה
רק 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
  • מספר handles, מספר חוטים
  • מספר פעולות או פריטים שעובדו

אם ה-Private Bytes של התהליך יציב בזמן ש-Commit של המערכת ממשיך לגדול, צריך להרחיב את ההיקף לתהליכים אחרים, לליבה, למנהלי התקנים ולמקטעים משותפים.

11.3. החליטו תחילה איזה “ממד” גדל

  • Working Set לבדו: דפים מתגוררים, משותפים או שמקורם בקובץ, Trim וטעינה מחדש
  • Private Bytes: Commit פרטי לתהליך
  • Virtual Bytes לבדו: Reserve, מיפוי, פיצול מרחב כתובות
  • System Commit לבדו: כולל תהליכים אחרים וצד הליבה
  • Nonpaged Pool: צד מנהל התקן/ליבה
  • Handles / GDI / USER: דליפות במשאבים שאינם זיכרון

לדלג על הסדר הזה ולקפוץ ישר ללקיחת dump פירושו לקרוא הר של מידע בזמן שמכוונים לדבר הלא נכון.

11.4. עברו לפירוט

  • תהליך native: VMMap, WinDbg, Application Verifier, מעקב ערימה
  • .NET: dotnet-counters, dotnet-gcdump, dotnet-dump, PerfView
  • ברמת המערכת: RAMMap, PerfMon, WPR/WPA
  • מאגר הליבה: PoolMon, WinDbg

VMMap מציג את הזיכרון הווירטואלי ה-committed של תהליך, ואת ה-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 גבוה אומר שמחליפים לדיסק

ניסוח מחדש: זה כולל גם soft fault. בדקו Pages Input/sec, Page Reads/sec והשהיית דיסק כדי לראות אם קלט/פלט דיסק מעורב בפועל.

תפיסה שגויה 5: 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, בפינוי דפים שהשתנו וב-dump של קריסה.
  • כתובת וירטואלית Reserved, דף Committed, ודף שנגעו בו בפועל ונכנס ל-Working Set הם שלבים נפרדים.
  • Page Fault הוא פעולה רגילה, ו-soft fault אינו קורא מהדיסק. גם hard fault יכולים להתרחש לא רק מקובץ הדפדוף אלא מ-EXE, DLL או קובץ ממופה.
  • דליפת זיכרון מוכחת לא לפי הגודל בנקודת זמן אחת, אלא לפי ערך הרצפה והמגמה אחרי אותו עומס, יחד עם הפירוט.
  • הנתיב הבסיסי: VMMap לפירוט של תהליך בודד, RAMMap ל-RAM פיזי ברמת המערכת, PerfMon לסדרת זמן, וכלי dump ייעודי למה שקורה בתוך סביבת ריצה.

בפעם הבאה שתשימו לב במנהל המשימות ש”הזיכרון גדל”, התחילו בשאלה הזו.

מה שגדל הוא Working Set, Private Bytes, Virtual Bytes או System Commit?

השאלה הזו לבדה הופכת את נקודת הכניסה לחקירה שלכם למדויקת בהרבה.

מאמרים קשורים

תחומי ייעוץ קשורים

KomuraSoft LLC מטפלת בחקירות סיבת שורש שמשלבות PerfMon, VMMap, RAMMap, WinDbg וכלי אבחון של .NET לגידול זיכרון של אפליקציות Windows, להידרדרות ביצועים אחרי הפעלה ממושכת, ל-OutOfMemory בתהליכי 32 סיביות, ולמחסור בזיכרון שמתרחש רק בסביבת הלקוח. אנחנו לא עוצרים ב”הזיכרון גבוה” — אנחנו מבודדים איזה אזור גדל, דרך איזו פעולה, למה, ומאין מפנים אליו או מחזיקים אותו.

מקורות

  1. Microsoft Learn, Working Set. על כך ש-Working Set של תהליך הוא קבוצת הדפים שכרגע מתגוררים בזיכרון פיזי, כולל דפים משותפים; על ההבדל בין soft page fault ל-hard page fault; על דפי 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. על כך שקובץ הדפדוף תומך בפינוי דפים שהשתנו, ב-dump של קריסת מערכת ובהרחבת 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; על כך ש-commit מחויב כנגד הזיכרון הכולל של המערכת וקובץ הדפדוף; ועל כך שהדף הפיזי בפועל לפעמים אינו מוקצה עד הגישה הראשונה.  2 3

  6. Microsoft Learn, How to determine the appropriate page file size for 64-bit versions of Windows. על כך שגודל קובץ הדפדוף תלוי בשיא Commit Charge ובדרישות dump הקריסה; על כך ש-hard page fault קוראים לא רק מקובץ הדפדוף אלא גם מ-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 הופך כל דף ל-copy-on-write פוטנציאלי, כך ש-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. על פירוק הזיכרון הווירטואלי ה-committed של תהליך לפי סוג, ועל הצגת הזיכרון הפיזי(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 הוא כמות הזיכרון ה-committed שמשמשת באופן בלעדי את אותו תהליך, בין אם הוא כרגע מתגורר ב-RAM ובין אם לא. לכן השניים לעולם אינם שווים, ואף אחד מהם אינו גדול יותר מהשני באופן עקבי.
האם "Committed 18/32GB" במנהל המשימות אומר שנכתבו 18GB לקובץ הדפדוף?
לא. הנתון השמאלי הוא סך ה-Commit שהמערכת כולה מבטיחה כרגע לגבות; הנתון הימני הוא תקרת ה-Commit שהמערכת יכולה לתמוך בה. התקרה נקבעת בערך לפי RAM ועוד קובץ הדפדוף, אבל לא כל הסכום השמאלי יושב בפועל בקובץ הדפדוף. רוב הדפים ה-committed נמצאים ב-RAM, ולחלק מהדפים ה-committed מעולם לא הוקצה דף פיזי. בינתיים, דפים שאפשר לטעון מחדש מקובץ המקור שלהם — כמו EXE, DLL וקבצים שממופים לזיכרון — לא בהכרח מעלים את ה-Commit הפרטי באותה כמות שבה הם מעלים את ה-Working Set.
האם אפשר לקבל OutOfMemory גם כשיש RAM פנוי?
כן. הקצאה יכולה להיכשל מסיבות שאינן RAM פיזי, כולל תהליך 32 סיביות שמכלה את מרחב הכתובות הווירטואלי, מחסור בטווח כתובות פנוי רציף, תקרת ה-Commit של המערכת, או מגבלות ייחודיות ל-Job Object או לסביבת הריצה. בפרט, תהליך 32 סיביות ב-Windows של 64 סיביות מוגבל בדרך כלל ל-2GB של מרחב כתובות וירטואלי במצב משתמש, אלא אם הוא Large Address Aware.
האם השבתת קובץ הדפדוף הופכת את Windows למהיר יותר?
אי אפשר להניח זאת ככלל. השבתת קובץ הדפדוף מורידה את תקרת ה-Commit של המערכת, מקשה לפנות מ-RAM דפים שהשתנו ואינם בשימוש, ומשפיעה על אופן הגדרת dump של קריסה. גודל קובץ הדפדוף צריך להיקבע לפי מדידת שיא ה-Commit Charge ולפי ה-dump של הקריסה שאתם צריכים — זו אינה הגדרה שמשביתים בלי הצדקה.
האם Page Faults/sec גבוה אומר שהמערכת קצרה בזיכרון?
אי אפשר לדעת מזה לבדו. תקלות דף כוללות soft fault, שאפשר לפתור מדפי Standby ב-RAM או מדפים משותפים עם תהליך אחר, ו-hard fault שקוראים מהדיסק. במקום להסתכל על Page Faults/sec בבידוד, בדקו Pages Input/sec, Page Reads/sec, Available MBytes, השהיית דיסק וזמן עיבוד יחד על אותו ציר זמן.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג