- Вопрос или проблема
- Решение PowerShell
- Поддерживающие ресурсы
- пример с блокнотом
- vmmap_parse.ps1
- результаты
- Ответ или решение
- Способы идентификации процессов, вы consuming выделенной памяти
- 1. Использование PowerShell
- 2. Использование Process Explorer
- 3. Использование Process Hacker
- 4. Использование RAMMap
- Примечания
- Заключение
Вопрос или проблема
Моя система использует большое количество выделенной памяти (из 8 ГБ ОЗУ + 2 ГБ файла подкачки 85% памяти выделено). Физическое использование составляет около 65%.
Как я могу определить, какие процессы выделяют большую часть выделенной памяти? Я понимаю, что память может быть разделена между процессами. До сих пор я использовал VMMap для отображения выделенной памяти, но это показывается на основе каждого процесса и не учитывает секции, поддерживаемые файлом подкачки.
Решение PowerShell
1. Получить 10 процессов, использующих наибольшее количество виртуальной памяти
(Get-Process | Sort-Object PagedMemorySize -Desc) | Select-Object Name, PagedMemorySize, VirtualMemorySize -First 10;
Пример вывода
Name VirtualMemorySize PagedMemorySize
---- ----------------- ---------------
explorer 1529909248 478908416
Microsoft.Photos 1303465984 433094656
javaw 886177792 185556992
MicrosoftEdgeCP 894496768 219799552
MicrosoftEdgeCP 874590208 202584064
MicrosoftEdgeCP 802746368 146792448
UrBackupClientBackend 685735936 548347904
MsMpEng 667783168 205774848
MBAMService 661987328 228876288
mstsc 440627200 185860096
2. Получить сумму всей выделенной виртуальной памяти
Get-WmiObject win32_operatingsystem | Select-Object @{N='commit';E={($_.totalvirtualmemorysize-$_.freevirtualmemory)*1KB/1GB}};
Пример вывода
commit
------
4.56205749511719
Поддерживающие ресурсы
“Количество виртуальной памяти, в байтах, которое связанный процесс запросил.”
TotalVirtualMemorySize
Тип данных:
uint64
Тип доступа:
Только для чтения
Квалификаторы:
Единицы ("килобайты")
Число, в килобайтах, виртуальной памяти. Например, это может быть рассчитано путем сложения общего объема ОЗУ с объемом пространства подкачки, то есть сложения объема памяти в или агрегированного компьютерной системой с свойством SizeStoredInPagingFiles.
“Получает объём страниц памяти, в байтах, выделенный для связанного процесса.”
“Объём памяти, в байтах, выделенный связанным процессом, который может быть записан в файл подкачки виртуальной памяти.”
Process Explorer может показать эту информацию по процессам:
Вот как получить вышеуказанный экран в Process Explorer:
- Нажмите меню View > Show Lower Pane
- Нажмите меню View > Lower Pane View > DLLs
- Нажмите меню View > Show Unnamed Handles and Mappings
- Щелкните на процесс в верхней панели
- Щелкните правой кнопкой мыши по заголовкам нижней панели и выберите Select Columns…
- На вкладке DLL отметьте Mapped Size и Mapping Type
- Нажмите OK
Process Hacker может аналогично показывать эту информацию, после выбора и двойного щелчка на процессе, в вкладке Handles снимите отметку Hide unnamed handles.
В списке процессов Process Explorer колонка “Private Bytes” показывает вклад каждого процесса в выделение. Не обязательно смотреть на представление нижней панели.
Убедитесь, что вы запускаете Process Explorer от имени администратора.
Диспетчер задач показывает ту же информацию на вкладке “Подробности” в колонке “Commit size”.
Обратите внимание, что то, что показывается в колонке “Память (частный рабочий набор)” в Диспетчере задач, — это не то же самое, хотя и используется слово “частный”. Это показывает подмножество выделения каждого процесса, которое в данный момент находится в ОЗУ для этого процесса.
Согласно Windows Internals, вкладчики в общий размер выделения:
- выделенная частная память в каждом процессе
- выделенная память, поддерживаемая файлом подкачки (не отображается в “частных байтах” процесса)
- регионы копирования при записи выделенной памяти
- Неподкачиваемый и подкачиваемый пул
- другие выделения в пространстве ядра, не поддерживаемые явным образом файлами (например, страничный код в драйверах или в ntoskrnl.exe не учитывается, так как он поддерживается соответствующими исполняемыми файлами)
- Ядро стеков – у каждого потока есть один
- Страницы таблиц
- Пространство для таблиц страниц, которые еще не были фактически выделены, но для которых уже существует выделенная память
- Выделения “Address Windowing Extension” (AWE)
Windows Internals более подробно объясняет, что из этого является и почему каждый из них считается общим размером выделения системы. К сожалению, для виртуальных размеров многих из этих вещей нет счетчиков, что и касается выделения. RAMmap показывает физические размеры некоторых из них, но не виртуальные.
Итак, из того, что я могу собрать, vmmap
похоже делает свои собственные вычисления (он действительно устанавливает драйвер в режиме ядра для правильной работы) и не использует API в win32_process
.
Вы можете в некотором роде пересчитать то, что он делает в графическом интерфейсе с помощью аргумента outfile <filename>
, который генерирует файл .mmp
, который представляет собой просто XML.
На самом деле выяснение вкладов в размеры выделения не кажется тривиальной задачей, поскольку “разделяемый” может быть как проблемой 1 процесса, так и многих в зависимости от обстоятельств. Частные данные чаще всего являются местом, где у вас будут утечки, но если вам просто важен размер, вы должны учитывать изображение, расширения адресов, AWE и т.д.
vmmap
– это отличное средство, но, похоже, оно написано с учетом профилирования производительности одного процесса.
Выступление на YouTube Марка Руссиновича (создателя sysinternals) очень познавательное: Тайны управления памятью раскрыты, с Марком Руссиновичем (Часть 1). Как упоминали другие, книги Windows Internals и Windows Troubleshooting (также Руссиновича) тоже полезны.
Довольно разочаровывающе, что эта информация не доступна прямо в ОС.
пример с блокнотом
Этот пример экспортирует единственный снимок из vmmap
для блокнота и читает его обратно. Затем он суммирует значение Commit
из определенных регионов. Это число, кажется, приближается к тому, что показано в графическом интерфейсе.
vmmap_parse.ps1
Сначала откройте копию блокнота. Вы также можете открыть vmmap
и осмотреть процесс для сравнения.
function New-VmMapLogFile {
#Requires -RunAsAdministrator
[CmdletBinding()]
param(
[Parameter(Mandatory=$True,ValueFromPipelineByPropertyName=$True)]
[Alias('id')]
[int32[]]
$Ids,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[string]
$DestinationPath = (Join-Path $PWD.Path "vmmap_$(get-date -f 'yyyyMMdd_HHmmss')"),
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[string]
$VmMapPath="c:\sysinternals\vmmap.exe"
)
BEGIN {
if(-not (Test-Path -Path $DestinationPath)) {
New-Item -Path $DestinationPath -ItemType 'container' -ea 1 | out-null
}
if(-not (Test-Path -Path $VmMapPath -PathType 'leaf')) {
throw "vmmap missing"
}
}
PROCESS {
foreach($id in $Ids) {
$proc = $null
$proc = Get-Process -Id $id -ea 0
if(-not $proc) {
write-warning "cannot find PID $($id)"
continue
}
[System.IO.FileInfo]$outputfile = Join-Path $DestinationPath "$($id).mmp"
write-verbose "creating $($outputfile.FullName)"
$vmmapProcArgs = @{
Wait = $True
FilePath = $VmMapPath
ArgumentList = @(
'-accepteula',
'-p',$id,
'outputfile',$outputfile.FullName
)
WindowStyle="hidden"
}
Start-Process @vmmapProcArgs
if(@(0) -notcontains $LASTEXITCODE) {
write-warning "vmmap PID $($id) returned: $($LASTEXITCODE)"
}
}
}}
function Import-VMMapLogFiles {
param(
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateScript({ Test-Path -Path $_ -PathType 'container' })]
[string]
$DirectoryPath
)
write-verbose "Checking dir $($DirectoryPath) for *.mmp files"
$mmpFiles = @(Get-ChildItem -Path $DirectoryPath -File -Filter '*.mmp')
write-verbose "$($mmpFiles.Count) files found"
foreach($mmpFile in $mmpFiles) {
$objProps = [ordered]@{
PID = $vmmap.root.PID
Process = $vmmap.root.Process
}
# read XML file
[xml]$vmmap = Get-Content -Path $mmpFile.FullName -Raw
$regions = @($vmmap.root.Snapshots.Snapshot.MemoryRegions.Region)
$regionByType = $regions | Group-Object -Property 'Type'
# examine regions
$totalCommitKb = 0
foreach($r in $regionByType) {
$keyPrefix = ($r.Name.ToLower() -replace '\s+','_')
# filter regions
$validRegions = @()
switch($r.Name) {
'Private Data' {
# 4096 regions only
$validRegions = @($R.Group | Where-Object { $_.Size - 4096 })
}
default {
$validRegions = @($R.Group)
}
}
# commited sum
$commitKeyRegex = 'image|shareable|private_data|heap|stack'
$commitRegions = @($validRegions | where-object { $_.Commit -gt 0 })
$commitBytes = ($commitRegions | Select-Object -ExpandProperty Commit | Measure-Object -Sum | Select-Object -ExpandProperty Sum)
$commitKb = $commitBytes / 1KB
$commitRounded = [math]::Round($commitKb, 2)
if($keyPrefix -match $commitKeyRegex) {
$totalCommitKb += $commitRounded
}
# size sum
$sizeBytes = 0
$sizeBytes = $validRegions | Select-Object -ExpandProperty Size | Measure-Object -Sum | Select-Object -ExpandProperty Sum
$sizeKb = $sizeBytes / 1KB
$sizeKbRounded = [math]::Round($sizeKb, 2)
# add properties
$objProps["$($keyPrefix)_kb"] = $sizeKbRounded
$objProps["$($keyPrefix)_commit_kb"] = $commitRounded
}
$objProps['commit_total_kb'] = $totalCommitKb
[pscustomobject]$objProps
}
}
$tmpDir = Join-Path $PSScriptRoot 'notepad'
Remove-Item -Path $tmpDir -recurse -force -ea 0 | out-null
get-process -name 'notepad' -ea 1 | New-VmMapLogFile -DestinationPath $tmpDir
Import-VMMapLogFiles -Verbose -DirectoryPath $tmpDir
результаты
из графического интерфейса
вывод скрипта
PID : 15320
Process : "C:\Windows\System32\notepad.exe"
free_kb : 135287120640
free_commit_kb : 0
private_data_kb : 4238760
private_data_commit_kb : 316
unusable_kb : 2904
unusable_commit_kb : 0
thread_stack_kb : 512
thread_stack_commit_kb : 80
heap_(shareable)_kb : 64
heap_(shareable)_commit_kb : 64
shareable_kb : 2147510224
shareable_commit_kb : 46412
mapped_file_kb : 23040
mapped_file_commit_kb : 23040
heap_(private_data)_kb : 4516
heap_(private_data)_commit_kb : 636
image_(aslr)_kb : 52720
image_(aslr)_commit_kb : 52720
commit_total_kb : 123268
Ответ или решение
Для идентификации процессов, потребляющих большую часть выделенной памяти на вашей системе, можно воспользоваться несколькими подходами и инструментами. Ваша задача заключается в выявлении процессов, занимающих наибольшее количество выделенной памяти, в то время как фактическое использование физической памяти составляет значительно меньший процент от общего объема. Вот некоторые шаги и инструменты, которые вы можете использовать для этой цели.
Способы идентификации процессов, вы consuming выделенной памяти
1. Использование PowerShell
PowerShell предоставляет мощные инструменты для анализа памяти процессов. Вы можете использовать следующие команды:
-
Получить 10 процессов, использующих наибольшее количество виртуальной памяти:
(Get-Process | Sort-Object PagedMemorySize -Desc) | Select-Object Name, PagedMemorySize, VirtualMemorySize -First 10;
Эта команда выдаст список процессов, отсортированных по размеру страниц, что поможет вам быстро определить, какие процессы используют наибольшее количество памяти.
-
Подсчитать общую выделенную виртуальную память:
Get-WmiObject win32_operatingsystem | Select-Object @{N='commit';E={($_.totalvirtualmemorysize-$_.freevirtualmemory)*1KB/1GB}};
Это даст вам представление о том, сколько памяти было выделено в системе в общей сложности.
2. Использование Process Explorer
Process Explorer – это инструмент от Sysinternals, который предоставляет подробную информацию о процессах, включая использование выделенной памяти.
Чтобы получить данные о выделенной памяти:
- Запустите Process Explorer с правами администратора.
- Включите нижнюю панель: Меню View > Show Lower Pane.
- Отобразите DLL: Меню View > Lower Pane View > DLLs.
- При выборе процесса в верхней панели вы можете увидеть количество "Private Bytes", которое отображает вклад каждого процесса в выделенную память.
Также вы можете использовать "Task Manager" для просмотра Столбца "Commit size" на вкладке "Details", чтобы быстро оценить размер выделенной памяти для каждого процесса.
3. Использование Process Hacker
Process Hacker предлагает похожие функции как и Process Explorer, но с дополнительной возможностью увидеть карту памяти. Просто выберите необходимый процесс и просмотрите вкладку "Handles", где можно найти информацию о различных типах выделенной памяти и ресурсах.
4. Использование RAMMap
RAMMap также может быть полезен для анализа размещения памяти в памяти вашей системы. Он позволяет увидеть, какие типы памяти используются в данной системе и как она распределена!
Примечания
- Обратите внимание, что память может быть разделяемой между процессами, и это требует внимательного анализа, чтобы избежать искажений в оцифровке использованных графиков.
- Существует множество других методов и инструментов, но использование вышеупомянутых инструментов является наиболее эффективным способом для быстрого получения информации о выделенной памяти на Windows-системах.
Заключение
Идентификация процессов, которые потребляют много выделенной памяти, может быть сложной задачей, особенно когда речь идет о совместно используемой памяти. С помощью утилит PowerShell, Process Explorer и Process Hacker, вы сможете эффективно получить информацию о использовании памяти и оптимизировать работу вашей системы. Рассмотрение, почему процессы используют такое количество памяти, также может помочь в будущем предсказании и устранении проблем с производительностью.