Що таке приватні байти, віртуальні байти, робочий набір?


490

Я намагаюся використовувати утиліту perfmon Windows для налагодження витоків пам'яті в процесі.

Ось як парфмон пояснює терміни:

Робочий набір - це поточний розмір робочого набору цього процесу в байтах. Робочий набір - це набір сторінок пам'яті, які останнім часом торкаються ниток у процесі. Якщо вільна пам'ять на комп’ютері перевищує поріг, сторінки залишаються в робочому наборі процесу, навіть якщо вони не використовуються. Коли вільна пам'ять опускається нижче порогового значення, сторінки обрізаються з робочих наборів. Якщо вони знадобляться, вони повернуться в робочий набір, перед тим як залишити основну пам'ять.

Віртуальні байти - це поточний розмір віртуального адресного простору в байтах, який процес використовує. Використання віртуального адресного простору не обов'язково означає відповідне використання або диска, або основних сторінок пам'яті. Віртуальний простір обмежений, і процес може обмежити його здатність завантажувати бібліотеки.

Приватні байти - це поточний розмір у байтах пам'яті, виділений цим процесом, який не можна поділитись з іншими процесами.

Це питання, які у мене є:

Це приватні байти, які я повинен вимірювати, щоб бути впевненим, чи має процес витік, оскільки він не передбачає жодних спільних бібліотек, а будь-які витоки, якщо вони відбудуться, будуть надходити від самого процесу?

Яка загальна пам'ять, яка споживається процесом? Це віртуальні байти чи це сума віртуальних байтів і робочого набору?

Чи є якесь відношення між приватними байтами, робочим набором та віртуальними байтами?

Чи є якісь інші інструменти, які дають краще уявлення про використання пам'яті?


3
Кращим інструментом буде valgrind / helgrind, але не під Windows, на жаль :(
Kornel Kisielewicz

Це приватний байт, чи слід міряти, щоб бути впевненим, чи не має витік процес. Якщо приватні байти процесу не зростають, то у вас немає витоків пам'яті. Якщо вони зростають, це може бути пов’язано з витоком пам’яті, а також через фрагментацію пам’яті. Я думаю, що важко сказати, дивлячись на зростання приватних байтів, що це означає саме.

@SergeiKurenkov Одне, що ми можемо сказати, це те, що НІКОЛИ б це не було пов'язано з "фрагментацією пам'яті".
Джеймі Ханрахан

Відповіді:


517

Коротка відповідь на це запитання полягає в тому, що жодне з цих значень не є надійним показником того, скільки пам’яті фактично використовується виконуваний файл, і жодне з них насправді не підходить для налагодження витоку пам’яті.

Байт відносяться до кількості пам'яті , що процес виконуваним вже просив - не обов'язково сума його фактичного використання . Вони є "приватними", оскільки вони (як правило) виключають файли, відображені в пам'яті (тобто спільні DLL-файли). Але ось ось у чому суть - вони не обов'язково виключають пам'ять, виділену цими файлами . Неможливо сказати, чи була зміна приватних байтів саме через виконуваний файл або через пов'язану бібліотеку. Приватні байти також не є виключно фізичною пам'яттю; вони можуть бути підключені до диску або до списку сторінок у режимі очікування (тобто більше не використовуються, але ще не є підказками).

Робочий набір позначає загальну фізичну пам'ять (ОЗП), яку використовує процес. Однак, на відміну від приватних байтів, сюди також входять файли з картографічною пам'яттю та різні інші ресурси, тому це навіть менш точне вимірювання, ніж приватні байти. Це те саме значення, про яке повідомляється в "Mem Використання" диспетчера завдань і є джерелом нескінченної сум'яття в останні роки. Пам'ять у Робочому наборі "фізична" в тому сенсі, що до неї можна звертатись без помилок сторінки; однак, список сторінок у режимі очікування також все ще фізично зберігається в пам’яті, але не повідомляється в Робочому наборі, і саме тому ви можете побачити, як «Використання пам’яті» раптом падає, коли ви мінімізуєте програму.

Віртуальні байти - це загальний віртуальний адресний простір, зайнятий усім процесом. Це схоже на робочий набір, в тому сенсі, що він включає в себе файли з картографічною пам'яттю (спільні DLL-файли), але він також включає дані в списку очікування та дані, які вже були викладені на сторінку, і десь сидять у файлі сторінок на диску. Загальна кількість віртуальних байтів, використовуваних кожним процесом у системі під великим навантаженням, збільшить значно більше пам’яті, ніж на машині насправді.

Отже відносини такі:

  • Приватні байти - це те, що ваша програма фактично виділила, але включає використання файлів сторінки;
  • Робочий набір - це нерозпізнані приватні байти плюс файли з картою пам'яті;
  • Віртуальні байти - це робочий набір плюс підписані приватні байти та список очікування.

Тут є ще одна проблема; подібно до того, як спільні бібліотеки можуть виділяти пам'ять у вашому модулі додатків, що призводить до потенційних помилкових позитивів, повідомлених у приватних байтах вашої програми , так само ваше додаток може виділити пам'ять всередині загальних модулів, що призводить до помилкових негативів . Це означає, що у вашій програмі фактично можливо витік пам’яті, який ніколи не виявляється у приватних байтах. Навряд чи, але можливо.

Приватні байти - це розумне наближення обсягу пам’яті, яку використовує ваш виконуваний файл, і його можна використовувати для звуження списку потенційних кандидатів на витік пам’яті; якщо ви бачите, що кількість постійно зростає та зростає, ви хочете перевірити цей процес на течію. Однак це не може довести, що витік є чи немає.

Один з найефективніших інструментів виявлення / виправлення витоків пам'яті в Windows - це насправді Visual Studio (посилання переходить на сторінку про використання VS для витоку пам'яті, а не на сторінці продукту). Раціональне очищення - це ще одна можливість. Microsoft також має більш загальний документ з найкращих практик з цього приводу. У цьому попередньому запитанні є більше інструментів .

Я сподіваюся, що це очистить кілька речей! Відстеження витоків пам’яті - одна з найскладніших речей, що потрібно зробити при налагодженні. Удачі.


26
Я боюся, що ви відповідаєте не зовсім коректно. Приватні байти посилаються на об'єм оперативної пам'яті (RAM), про який вимагає виконуваний процес - не лише фізичну пам'ять. Таким чином, ви можете точно перевірити більшість випадків витоку пам'яті, відстежуючи приватні байти. Спробуйте :: VisualAlloc створити великий фрагмент пам'яті (скажімо, 1.5G). Ви повинні бачити, що ваші приватні байти набагато більше робочого набору. Що доводить, що ваш "Робочий набір - це приватні байти плюс файли, відображені на пам'ять", невірно.
Джей Чжу

4
Насправді, я вважаю, що розуміння запису таке: "Робочий набір - це приватні байти в пам'яті плюс файли, відображені на пам'ять". І приватні байти МОЖУТЬ бути замінені - ви можете бачити приватні байти більше, ніж фізична пам'ять, яку ви маєте в апараті.
Джей Чжу

2
@Aaronaught: Ваше перше твердження про надійний індикатор і відповідне для налагодження є заплутаним. Приватні байти - надійний показник протікання місця в пам'яті програми. Це може бути залежною від DLL і непрямою, але це витік у просторі пам'яті додатків. Чи можете ви пояснити, чому його не можна використовувати для налагодження? повна пам’ять пам’яті процесу подання заявки повинна нам підказувати, що споживає ця пам’ять. Я не впевнений, що розумію, чому його не можна використовувати для налагодження. Ви можете пролити трохи світла?
G33kKahuna

@ G33kKahuna: Мені незрозуміло, як дамп пам’яті скаже тобі, що споживає пам'ять у будь-якому змістовному сенсі - хіба що під «що» ви маєте на увазі «які модулі», але тоді все, що у вас є, це знімок, ви все одно не можете побачити який модуль фактично просочується пам'яттю з часом, якщо ви не зробите кілька скидів у часі та при жорсткому контрольованих умовах. Важко уявити більш неефективну та ненадійну стратегію налагодження. Профілі є скрізь скрізь; використовувати один.
Aaronaught

1
Виконати повний! Objsize, це повинно відображати будь-які закріплені об’єкти в безпосередній купі. Ви можете підтвердити, перевіривши eeheap -gc. Це повинно показати вам, де гучність застрягла. Як правило, якщо немає підказок з усіма перерахованими вище командами, ваші приватні байти споживаються незабраними об’єктами в GC. Тепер переходимо до gchandles або gcleaks. Ці команди повинні вказувати вам, які типи / адресу об'єкта неможливо відобразити. Вказівник все ще є, але об'єкта немає. Це така категорична проблема для неопублікованих обробників подій.
G33kKahuna

10

Не слід намагатися використовувати perfmon, диспетчер завдань чи будь-який подібний інструмент для визначення витоків пам'яті. Вони гарні для виявлення тенденцій, але не багато іншого. Номери, про які вони повідомляють в абсолютних значеннях, занадто розпливчасті та зведені, щоб бути корисними для конкретного завдання, такого як виявлення витоку пам'яті.

Попередня відповідь на це запитання дала чудове пояснення, що таке різні типи.

Ви запитаєте про рекомендацію щодо інструменту: я рекомендую валідатор пам'яті. Можливий для моніторингу програм, які здійснюють мільярди розподілу пам'яті.

http://www.softwareverify.com/cpp/memory/index.html

Відмова: Я спроектував перевірку пам’яті.


1
Я навіть не можу запустити простий файл класу (на Java)? Що дає?
jn1kk

Я підозрюю, що Стівен і Чорт якимось чином пов’язані або навіть клоновані ...: D;)
Роберт Коритник

@StephenKellett, Чи є пробна версія?
Пейс’єр

@Pacerier, якщо ви переходите за посиланням, пробна версія для версій x86 та x64 трохи вище опції покупки зліва на сторінці.
Бредлі А. Тетро

10

Визначення лічильників парфмонів було порушено з самого початку, і чомусь, здається, занадто важко виправити.

Хороший огляд управління пам’яттю Windows доступний у відео « Таємниці управління пам’яттю розкрито » на MSDN: Він охоплює більше тем, ніж потрібно для відстеження витоків пам’яті (наприклад, управління робочим набором), але дає достатньо деталей у відповідних темах.


Щоб підказати про проблему з описом лічильників perfmon, ось внутрішня історія про приватні байти з " Лічильника ефективності приватних байтів - будьте обережні ! " На MSDN:

Питання: Коли приватний байт не є приватним байтом?

A: Коли він не є резидентом.

Лічильник приватних байт повідомляє про відповідальність за здійснення комісії. Тобто, обсяг місця, який було виділено у файлі swap, для вмісту вмісту приватної пам'яті у випадку, якщо він замінений. Примітка: Я уникаю слова "зарезервовано" через можливе плутанину з віртуальною пам'яттю в зарезервованому стані, яке не вчинено.


З розділу "Планування ефективності " на MSDN:

3.3 Приватні байти

3.3.1 Опис

Приватна пам'ять, визначається як пам'ять, виділена для процесу, який не може бути спільним для інших процесів. Ця пам'ять коштує дорожче, ніж спільна пам'ять, коли на машині виконується кілька таких процесів. Приватна пам'ять у (традиційних) некерованих dll зазвичай складається з C ++ статики і становить близько 5% від загального робочого набору dll.


1
голосувати вгору через шалено хороших прикладів того, як це порушено!
Бруно Брант

Перша цитата помилкова. Виділення "Приватних байтів" не вимагає, щоб нічого було "виділено у файлі swap" (який насправді називається файл сторінки). Вам навіть не потрібно мати файл сторінки для виділення "приватних байтів". Насправді, виділяючи приватні байти не відразу використовувати будь-який простір де - небудь , і не може коли - або використовувати стільки , скільки було виділено.
Джеймі Ханрахан

Друга цитата не набагато краща. Приватні байти, використовувані в коді DLL, не обов'язково здебільшого статично розподіляються в межах DLL. Код DLL абсолютно вільний для виклику VirtualAlloc, HeapAlloc (malloc та новий у CRTL) тощо. Він також намагається описати розмір приватної пам'яті у відсотках від розміру робочого набору, що є безглуздим. Перший - це віртуальний розмір (і буде однаковим для кожного використання коду з однаковим входом), а другий - фізичним (що може кардинально відрізнятися від одного запуску до другого, залежно від того, наскільки багато пам'яті чи - голодував автомат).
Джеймі Ханрахан

5

Тут є цікава дискусія: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ Моє розуміння цієї теми полягає в тому, що звільнення невеликих асигнувань не відображено в приватних байтах чи робочому наборі.

Довга історія:

якщо я подзвоню

p=malloc(1000);
free(p);

то Приватні байти відображають лише розподіл, а не угоду.

якщо я подзвоню

p=malloc(>512k);
free(p);

то Приватні байти правильно відображають розподіл та угоду.


7
Це пояснюється тим, що в стандартних функціях пам'яті бібліотеки C використовується користувацька або Win32 Heap, яка є механізмом управління пам’яттю поверх управління низькорівневим процесом управління пам'яттю.
Киберія

@Kyberias, Тож як ми можемо потрапити нижче цього?
Pacerier

поки (1) вільний (малок (1000)); // Чи призведе це до того, що приватні байти зростуть назавжди?
франкшпік

2
@franckspike: ні, він збільшиться до певного моменту (як правило, близько 4 кБ, але це може змінюватися), а потім припиниться, тому що CRT повторно використовуватиме раніше звільнену пам'ять замість того, щоб вимагати нових сторінок в ОС.
Міраль

@Pacerier: Ви можете зателефонувати на VirtualAlloc та VirtualFree.
Джеймі Ханрахан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.