Как определить, какой процесс выделил память

Вопрос или проблема

Моя система использует большое количество выделенной памяти (из 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

результаты

из графического интерфейса

vmmap GUI

вывод скрипта

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, который предоставляет подробную информацию о процессах, включая использование выделенной памяти.

Чтобы получить данные о выделенной памяти:

  1. Запустите Process Explorer с правами администратора.
  2. Включите нижнюю панель: Меню View > Show Lower Pane.
  3. Отобразите DLL: Меню View > Lower Pane View > DLLs.
  4. При выборе процесса в верхней панели вы можете увидеть количество "Private Bytes", которое отображает вклад каждого процесса в выделенную память.

Также вы можете использовать "Task Manager" для просмотра Столбца "Commit size" на вкладке "Details", чтобы быстро оценить размер выделенной памяти для каждого процесса.

3. Использование Process Hacker

Process Hacker предлагает похожие функции как и Process Explorer, но с дополнительной возможностью увидеть карту памяти. Просто выберите необходимый процесс и просмотрите вкладку "Handles", где можно найти информацию о различных типах выделенной памяти и ресурсах.

4. Использование RAMMap

RAMMap также может быть полезен для анализа размещения памяти в памяти вашей системы. Он позволяет увидеть, какие типы памяти используются в данной системе и как она распределена!

Примечания

  • Обратите внимание, что память может быть разделяемой между процессами, и это требует внимательного анализа, чтобы избежать искажений в оцифровке использованных графиков.
  • Существует множество других методов и инструментов, но использование вышеупомянутых инструментов является наиболее эффективным способом для быстрого получения информации о выделенной памяти на Windows-системах.

Заключение

Идентификация процессов, которые потребляют много выделенной памяти, может быть сложной задачей, особенно когда речь идет о совместно используемой памяти. С помощью утилит PowerShell, Process Explorer и Process Hacker, вы сможете эффективно получить информацию о использовании памяти и оптимизировать работу вашей системы. Рассмотрение, почему процессы используют такое количество памяти, также может помочь в будущем предсказании и устранении проблем с производительностью.

Оцените материал
Добавить комментарий

Капча загружается...