[Mac] footprint man翻译和理解
NAME
footprint - 收集有关一个或多个进程的内存信息
footprint – gathers memory information about one or more processes
SYNOPSIS
footprint [-j path] [-f bytes|formatted|pages] [--sort column]
[-p name|pid] [-x name|pid] [-t] [-s] [-v] [-y] [-w]
[--swapped] [--wired] [-a] process-name | pid | memgraph [...]
footprint --sample interval ...
footprint -h, --help
DESCRIPTION
footprint工具收集和显示指定进程或memory graph files的内存消耗信息.
footprint将显示指定进程的所有可寻址内存,但是它强调被内核标记位'dirty'的内存用于统计。如果多个进程被指定,footprint将对多个映射对象进行重复数据消除,并将共享对象和私有对象分开展示。
如果想通过footprint查看不属于当前用户的进程,必须以root身份运行。
可以通过PID、精确进程名称或者部分进程名称指定进程,footprint将显示匹配到的所有进程的内存信息。
The footprint utility gathers and displays memory consumption information for the specified processes or memory graph files.
footprint will display all addressable memory used by the specified processes, but it emphasizes memory considered 'dirty' by the kernel for purposes of accounting. If multiple processes are specified, footprint will de-duplicate multiply mapped objects and will display shared objects separately from private ones.
footprint must be run as root when inspecting processes that are not owned by the current user.
Processes are specified using a PID, exact process name, or partial process name. Memory information will be displayed for all processes matching any provided name.
OPTIONS
- -a,--all
针对所有进程(将花费更长时间) - -j, --json path
同时将数据以json形式保存到指定路径
样例: footprint -p [pid] -j /User/xx/footprint/ft.txt - -f, --format bytes|formatted|pages
文本输出应格式化为字节(bytes)、页面(pages)或人类可读格式化(默认,formatted)
样例: footprint -p [pid] -f pages - -sort column
文本输出应按给定列名排序,例如dirty(默认)、clean、category等。
样例: footprint -p [pid] -sort Category - -p, --proc name
按名称以给定进程为目标(可多次使用)
样例: footprint -p Chrome 比如浏览器多标签场景,可以通过此命令采集所有进程名带Chrome的进程,输出每个进程的分类占用,以及所有进程相加的总和。 - -p, --pid pid
按pid指定进程 - -x, --exclude name/pid
按名称或pid排除给定的进程(可以多次使用),经常与--all一起使用,以将某些进程排除在分析之外 - -t, --targetChildren
除了指定进程,也将他们的子进程、子进程的子进程全部加入统计。 - -s, --skip(没明白啥意思)
跳过被标记dirty且没有未完成的XPC事务(即,“clean”)的进程, - --forkCorpse(没明白啥意思)
分析目标进程的分叉尸体,而不是原始进程。由于系统资源对尸体的限制,此参数与--all或试图分析多个进程时不兼容。 - -v
显示所有区域和类似vmmap的地址空间布局输出。如果没有此标志,默认输出是每个内存类别的总计摘要。 - -w,--wide
显示所有列和完整路径的宽输出(等价于 --swapped --wired, 即增加了Swapped和Wired两列) - --swapped
显示swapped/compressed列 - --wired
显示 wired列 - --vmObjectDirty
将脏内存解释为内核中的VM objects视图,而不是通过pmap解释脏内存的默认行为。此模式可能会计算出与其他工具(如top(1)或活动监视器)中显示的大小不匹配的总占用空间。但是,它可以提供对设计中不包括在默认模式中的脏内存的深入了解,例如脏file-backed内存或VM region通常仅计入创建该内存的进程。 - --unmapped
在所有进程中搜索目标进程拥有但未映射到其地址空间的内存(有关更多详细信息,请参阅内存会计中的讨论) - --sample interval
在采样模式下开始footprint,每间隔时间内收集数据(可以是0.5等小数)。文本输出将是通常文本输出与添加的时间戳的串联。JSON输出将包含一个“示例”数组,其中包含许多通常位于顶级的相同键/值。采样模式下也支持所有其他命令行选项。
样例: footprint -p wpsoffice -w --sample 5 >/User/huawei/footprint/sample.txt 会将数据输出到文本,每次采样前会打印一行时间戳。
-a, --all
target all processes (will take much longer)
-j, --json path
also save a JSON representation of the data to the specified path
-f, --format bytes|formatted|pages
textual output should be formatted in bytes, pages, or human-
readable formatted (default)
--sort column
textual output should be sorted by the given column name, for
example dirty (default), clean, category, etc.
-p, --proc name
target the given process by name (can be used multiple times)
-p, --pid pid
target the given process by pid (can be used multiple times)
-x, --exclude name/pid
exclude the given process by name or pid (can be used multiple
times)
often used with --all to exclude some processes from analysis
-t, --targetChildren
in addition to the supplied processes, target their children,
grandchildren, etc.
-s, --skip
skip processes that are dirty tracked and have no outstanding XPC
transactions (i.e., are "clean")
--forkCorpse
analyze a forked corpse of the target process rather than the
original process. Due to system resource limits on corpses this
argument is not compatible with --all or if attempting to analyze
more than a couple processes.
-v display all regions and vmmap-like output of address space
layout.
Without this flag the default output is a summary of the totals
for each memory category.
-w, --wide
show wide output with all columns and full paths (implies
--swapped --wired)
--swapped
show swapped/compressed column
--wired
show wired memory column
--vmObjectDirty
interpret dirty memory as viewed by VM objects in the kernel,
rather than the default behavior which interprets dirty memory
through the pmap. This mode may calculate a total footprint that
does not match what is shown in other tools such as top(1) or
Activity Monitor.app. However, it can provide insight into dirty
memory that is by design not included in the default mode, such
as dirty file-backed memory or a VM region mapped into a process
that is normally accounted to only the process that created it.
The --vmObjectDirty mode was the default in versions prior to
macOS 10.15.
--unmapped
search all processes for memory owned by the target processes but
not mapped into their address spaces (see the discussion in
MEMORY ACCOUNTING for more details)
--sample interval
Start footprint in sampling mode, gathering data every interval
seconds (which can be fractional like 0.5). Text output will be a
concatenation of usual text output with added timestamps. JSON
output will contain a "samples" array with many of the same
key/values that would normally be at the top level. All other
command line options are also supported in sampling mode.
-h, --help
display help and exit
COLUMNS
括号之间的列名表示它们是一个或多个非括号列的子集
- Dirty
由进程写入的内存,包括交换(Swapped)、可清除的非易失性内存(purgeable non-volatile)和隐式写入的内存,如zero-filled。进程的footprint等于所有脏内存的总和。 - (Swapped)
"Dirty"内存的子集,已被内核压缩或换出的内存。 - Clean
既不是"Dirty"也不是可回收("Reclaimable")的常驻内存 - Reclaimable 可回收内存
已明确标记为可重复使用的驻留内存。当内存被设置为可清除(purgeable)时,或通过使用madvise(2)函数标记内存释放策略为MADV_FREE,将其标记为可回收。可回收内存可以随时从进程中取出,以响应系统内存压力。 - (Wired)
已经被锁定的内存(比如通过mlock函数锁定的内存),无法被换出,属于"Dirty"的一部分 - Regions(么看懂)
VM regions计数,共享缓存区域中包含的每个二进制段都被视为一个单独的区域,以便进行显示。 - Category
该类别的描述性名称,例如VM_MEMORY_*标记的人类可读名称、映射文件路径或加载的二进制文件的段。
Column names between parentheses indicate that they are a subset of one
or more non-parenthesized columns.
Dirty Memory that has been written to by a process, which includes
"Swapped", purgeable non-volatile memory, and implicitly
written memory such as zero-filled. A process's footprint is
equal to the total of all dirty memory.
(Swapped) A subset of "Dirty" memory that has been compressed or
swapped out by the kernel.
Clean Resident memory which is neither "Dirty" nor "Reclaimable".
Reclaimable Resident memory that has been explicitly marked as available
for reuse. Memory can be marked reclaimable when it is made
purgeable volatile (including purgeable empty) or by using
madvise(2) with advice such as MADV_FREE. Reclaimable memory
can be taken away from a process at any time in response to
system memory pressure.
(Wired) Memory that has been wired down (e.g., by calling mlock(2)
). This memory is usually a subset of "Dirty" and cannot be
paged out.
Regions The count of VM regions contributing to this entry. Each
binary segment contained within the shared cache region is
considered a separate region for display purposes.
Category A descriptive name for this entry, such as a human-readable
name for a VM_MEMORY_* tag, a path to a mapped file, or a
segment of a loaded binary.
INVESTIGATING MEMORY FOOTPRINT(调查内存足迹)
footprint提供了进程内存足迹的有效计算,并对导致该足迹的各种类型内存进行了高级概述。它提供的细节可以作为调查的起点。
- 优先减少“Dirty”内存。脏内存不能被内核自动回收,操作系统的各个部分直接使用,作为进程对系统内存压力的贡献的衡量标准
- 接下来,重点是减少“Reclaimable”内存,特别是可清除内存,当标记为非易失性(non-volatile)时,它将变得'Dirty'。虽然内核可以便宜地回收此内存,但可清除的易失性内存通常用作数据缓存,对于用户进程来说,这些数据可能会很昂贵(例如解码的图像数据)。
- “Clean”内存也可以被内核廉价地占用,但与“Reclaimable”不同的是,它可以由内核自动恢复,而无需用户进程的帮助。例如,可以自动从内存中删除干净的文件备份(file-backed)数据,并按需从磁盘重新读取。拥有过多的干净内存仍然可能是一个性能问题,因为在低内存情况下,大型工作集在加载和卸载进程的各个部分时可能会导致颠簸(thrashing)。
- 最后,尽可能避免使用“Wired”内存,因为它不能被分页或回收。
内存分类:
- Malloc memory
由malloc()函数分配的内存是最常见的内存形式之一,构成通常被称为“堆”的内存。此内存将有一个以“MALLOC_”为前缀的类别。malloc(3)代表进程分配VM regions;这些区域的内容将是代表进程中对象和数据的单个分配。请参阅heap命令以进一步分类包含在malloc内存区域中的对象,或leaks命令以检测内存泄露。 - Binary segments
加载的二进制文件将作为具有段类型和 二进制(通常是__TEXT段、__DATA段或__LINKEDIT段)的路径。 非共享缓存二进制文件和__DATA段中的页面(例如那些 包含修改的全局变量)通常具有脏内存。 - Mapped files
使用 mmap()函数分配的"File-backed"内存将显示为mapped file,对应的文件也将显示 - VM allocations
大多数其他类型的内存都可以使用指示名称进行标记(参见 mmap()函数了解更多信息)。例如,Foundation.framework可以分配内存和 用 VM_MEMORY_FOUNDATION 标记它,在footprint的输出中显示为“Foundation”。进程能够使用自己的标记分配内存,方法是在 范围 VM_MEMORY_APPLICATION_SPECIFIC_1-VM_MEMORY_APPLICATION_SPECIFIC_16内分配。这样内存不属于以前的类别之一,也不会将被标记为“untagged” (“VM_ALLOCATE”)”。 - Kernel memory
在分析kernel_task的特殊情况下,footprint的输出和类别将反映很多的数据也可以通过 zprint(1) 获得。这是由内核或内核扩展分配,通常不可直接到用户空间。尽管访问受限,用户空间程序通常影响内核分配内存的时间和数量(例如,对于代表用户进程分配的资源)。
对于 malloc 和 VM 分配的内存,有关时间和位置的详细信息 分配的内存通常可以通过启用MallocStackLogging和使用 malloc_history(1)查看每次分配时的回溯来获得。Xcode和Instruments提供用于调试内存的可视化工具。
vmmap(1) 提供了与 footprint类似的视图,但重点是显示内核返回的原始指标,而不是简化的加工过的已处理视图。一个重要的不同之处在于 vmmap(1) 的 “DIRTY” 列 不包括在 “SWAPPED”列。此外,vmmap(1) 可以仅对单个进程进行操作,并包含其他信息,例如malloc zone总结。
footprint provides an efficient calculation of a process's memory
footprint and a high-level overview of the various categories of memory
contributing to that footprint. The details that it provides can be used
as a starting point in an investigation.
Prioritize reducing "Dirty" memory. Dirty memory cannot be automatically
reclaimed by the kernel and is directly used by various parts of the OS
as a measure of a process's contribution to system memory pressure.
Next, focus on reducing "Reclaimable" memory, especially purgeable
volatile memory which will become dirty when marked non-volatile.
Although this memory can be cheaply reclaimed by the kernel, purgeable
volatile memory is commonly used as a cache of data that may be expensive
for a user process to recreate (such as decoded image data).
"Clean" memory can also be cheaply taken by the kernel, but unlike
"Reclaimable" it can be restored automatically by the kernel without the
help of a user process. For example, clean file backed data can be
automatically evicted from memory and re-read from disk on-demand. Having
too much clean memory can still be a performance problem, since large
working sets can cause thrashing when loading and unloading various parts
of a process under low memory situations.
Lastly, avoid using "Wired" memory as much as possible since it cannot be
paged out or reclaimed.
Malloc memory
Memory allocated by malloc(3) is one of the most common forms of
memory, making up what is usually referred to as the 'heap'. This
memory will have a category prefixed with 'MALLOC_'. malloc(3)
allocates VM regions on a process's behalf; the contents of those
regions will be the individual allocations representing objects
and data in a process. Refer to the heap(1) tool to further
categorize the objects contained within a malloc memory region,
or leaks(1) to detect a subset of heap memory that is no longer
reachable.
Binary segments
Loaded binaries will be visible as an entry with both the segment
type and the path to the binary, most often __TEXT, __DATA, or
__LINKEDIT segments. Non-shared cache binaries and pages in the
__DATA segment (such as those that contain modified global
variables) can often have dirty memory.
Mapped files
File-backed memory allocated using mmap(2) will show up as
'mapped file' along with the path to the file.
VM allocations
Most other types of memory can be tagged with a name that
indicates what subsystem allocated the region (see mmap(2) for
more information). For instance, Foundation.framework may
allocate memory and tag it with VM_MEMORY_FOUNDATION, which
appears in footprint's output as 'Foundation'. Processes are able
to allocate memory with their own tags by using an appropriate
tag in the range
VM_MEMORY_APPLICATION_SPECIFIC_1-VM_MEMORY_APPLICATION_SPECIFIC_16.
Memory which does not fall into one of the previous categories
and has not been explicitly tagged will be marked 'untagged
("VM_ALLOCATE")'.
Kernel memory
In the special case of analyzing kernel_task, footprint's output
and categories will mirror much of the data also available via
zprint(1). This is memory allocated by the kernel or a kernel
extension and is generally unavailable to userspace directly.
Despite the restricted access, userspace programs often influence
when and how much memory the kernel allocates (e.g., for
resources allocated on behalf of a user process).
For malloc and VM allocated memory, details about when and where the
memory was allocated can often be obtained by enabling MallocStackLogging
and using malloc_history(1) to view the backtrace at the time of each
allocation. Xcode.app and Instruments.app also provide visual tools for
debugging memory, such as the Xcode's Memory Graph Debugger.
vmmap(1) provides a similar view to footprint, but with an emphasis on
displaying the raw metrics returned by the kernel rather than the
simplified and more processed view of footprint. One important
difference is that vmmap(1)'s "DIRTY" column does not include the
compressed or swapped memory found in the "SWAPPED" column.
Additionally, vmmap(1) can only operate on a single process and contains
additional information such as a malloc zone summary.
MEMORY ACCOUNTING
确定应该考虑和不应该考虑哪些脏内存计算到一个进程是一个难题。内存可以由许多进程共享,有时可以由其他进程代表您分配,并且无论统计如何进行,准确计算往往都很昂贵。
许多操作系统历来公开内存指标 例如虚拟大小(VSIZE)和驻留大小(RSIZE/RPRVT/RSS/等)。 诸如此类的指标本身就很有用,但并不好 进程运行所需的物理内存量的指示器 (以及进程应用于系统的内存压力)。 例如,虚拟大小包括可能不受支持的分配 物理内存和驻留大小包括干净和易失性可清除 内核可以回收的内存(如前所述)。
另一方面,分析底层 VM 报告的脏内存 映射到流程中的对象(采用的方法)虽然更准确,但成本很高 并且对于需要经常知道 进程的内存占用量。--vmObjectDirty
许多操作系统历史上都公开了内存度量,如虚拟大小(VSIZE)和驻留大小(RSIZE/RPRVT/RSS/等)。像这样的度量在其本身方面很有用,但并不是进程运行所需的物理内存量(以及进程应用于系统的内存压力)的很好的指标。例如,虚拟大小包括可能不受物理内存支持的分配,驻留大小包括可由内核回收的干净和易失性可清除内存(如前所述)。另一方面,分析映射到进程中的底层VM对象报告的脏内存(--vmObjectDirty采取的方法)虽然更准确,但对于需要经常了解进程内存占用空间的系统来说,成本高昂,而且无法实时完成。
相反,苹果平台通过在内核中使用每个进程的分类账来跟踪“物理足迹”,该分类账由pmap和其他子系统保持最新。此分类帐查询便宜,适当准确,并提供了其他功能,如跟踪峰值内存,以及为一个进程不再映射到其中或可能已由另一个进程分配的内存收费的能力。如果占用空间无法分析未映射到进程中的“物理占用空间”部分,则此内存将被列为“Owned physical footprint
(unmapped)”。如果此内存被映射到另一个serspace进程,则可以使用--unmaped参数在所有进程中搜索同一VM对象的映射,如果找到该映射,将提供更好的描述,以及哪个进程映射了内存。默认情况下,当通过--all瞄准所有进程时,也会发生这种情况。在使用--unmaped后,任何仍被列为“(unmaped)”的内存都可能不会映射到任何用户空间进程中,而是仅由内核或驱动程序引用。此“physical footprint”分类帐的确切定义很复杂,可能会更改,但只要说占用空间的默认模式旨在提供与分类帐报告的值匹配的准确内存细分就足够了。大多数其他诊断工具,如top中的“MEM”列、活动监视器中的“MEM”列和Xcode中的内存调试仪表,都会查询此分类帐以填充其度量。
物理占用空间可能被拆分为多个子类别,如网络相关的内存、图形等。当内存分配(直接映射到进程中,或拥有但未映射)具有这样的分类时,足迹将将其附加到类别名称,如“IOKit(graphics)”或“Owned physical footprint
(unmapped) (media)”。
Determining what dirty memory should and should not be accounted to a
process is a difficult problem. Memory can be shared by many processes,
it can sometimes be allocated on your behalf by other processes, and no
matter how the accounting is done can often be expensive to accurately
calculate.
Many operating systems have historically exposed memory metrics such as
Virtual Size (VSIZE) and Resident Size (RSIZE/RPRVT/RSS/etc.). Metrics
such as these, which are useful in their own respect, are not great
indicators of the amount of physical memory required by a process to run
(and therefore the memory pressure that a process applies to the system).
For instance, Virtual Size includes allocations that may not be backed by
physical memory, and Resident Size includes clean and volatile purgeable
memory that can be reclaimed by the kernel (as described earlier).
On the other hand, analyzing the dirty memory reported by the underlying
VM objects mapped into a process (the approach taken by --vmObjectDirty),
while more accurate, is expensive and cannot be done in real-time for
systems that need to frequently know the memory footprint of a process.
Apple platforms instead keep track of the 'physical footprint' by using a
per-process ledger in the kernel that is kept up-to-date by the pmap and
other subsystems. This ledger is cheap to query, suitably accurate, and
provides additional features such as tracking peak memory and the ability
to charge one process for memory that is no longer mapped into it or that
may have been allocated by another process. In cases where footprint is
unable to analyze a portion of 'physical footprint' that is not mapped
into a process, this memory will be listed as 'Owned physical footprint
(unmapped)'. If this memory is mapped into another userspace process then
the --unmapped argument can be used to search all processes for a mapping
of the same VM object, which if found will provide a better description
and what process(s) have mapped the memory. This also happens by default
when targeting all processes via --all. Any memory still listed as
"(unmapped)" after using --unmapped is likely not mapped into any
userspace process and instead only referenced by the kernel or drivers.
The exact definition of this 'physical footprint' ledger is complicated
and subject to change, but suffice it to say that the default mode of
footprint aims to present an accurate memory breakdown that matches the
value reported by the ledger. Most other diagnostic tools, such as the
'MEM' column in top(1), the 'Memory' column in Activity Monitor.app, and
the Memory Debug Gauge in Xcode.app, query this ledger to populate their
metrics.
Physical footprint can be potentially be split into multiple
subcategories, such as network related memory, graphics, etc. When a
memory allocation (either directly mapped into a process, or owned but
unmapped) has such a classification, footprint will append it to the
category name such as 'IOKit (graphics)' or 'Owned physical footprint
(unmapped) (media)'.
SEE ALSO
vmmap(1), heap(1), leaks(1), malloc_history(1), zprint(1)