Linux 如何测量应用程序或进程的实际内存使用情况?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/131303/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:31:33  来源:igfitidea点击:

How to measure actual memory usage of an application or process?

linuxmemoryprocess

提问by ksuralta

This question is covered herein great detail.

这个问题在这里有很详细的介绍。

How do you measure the memory usage of an application or process in Linux?

你如何测量 Linux 中应用程序或进程的内存使用情况?

From the blog article of Understanding memory usage on Linux, psis not an accurate tool to use for this intent.

了解 Linux 上的内存使用情况的博客文章来看,ps并不是用于此目的的准确工具。

Why psis "wrong"

Depending on how you look at it, psis not reporting the real memory usage of processes. What it is really doing is showing how much real memory each process would take up if it were the only process running. Of course, a typical Linux machine has several dozen processes running at any given time, which means that the VSZ and RSS numbers reported by psare almost definitely wrong.

为什么ps是“错”

取决于您如何看待它,ps不会报告进程的实际内存使用情况。它真正做的是显示如果每个进程是唯一运行的进程,它将占用多少实际内存。当然,典型的 Linux 机器在任何给定时间都有几十个进程在运行,这意味着 VSZ 和 RSS 数字ps几乎肯定是错误的

采纳答案by ypnos

With psor similar tools you will only get the amount of memory pages allocated by that process. This number is correct, but:

使用ps或类似的工具,您将只能获得该进程分配的内存页面数量。这个数字是正确的,但是:

  • does not reflect the actual amount of memory used by the application, only the amount of memory reserved for it

  • can be misleading if pages are shared, for example by several threads or by using dynamically linked libraries

  • 不反映应用程序实际使用的内存量,只反映为它保留的内存量

  • 如果页面是共享的,例如由多个线程或使用动态链接库共享,则可能会产生误导

If you really want to know what amount of memory your application actually uses, you need to run it within a profiler. For example, valgrindcan give you insights about the amount of memory used, and, more importantly, about possible memory leaks in your program. The heap profiler tool of valgrind is called 'massif':

如果您真的想知道您的应用程序实际使用了多少内存,您需要在分析器中运行它。例如,valgrind可以让您深入了解使用的内存量,更重要的是,了解程序中可能存在的内存泄漏。valgrind 的堆分析器工具称为“massif”:

Massif is a heap profiler. It performs detailed heap profiling by taking regular snapshots of a program's heap. It produces a graph showing heap usage over time, including information about which parts of the program are responsible for the most memory allocations. The graph is supplemented by a text or HTML file that includes more information for determining where the most memory is being allocated. Massif runs programs about 20x slower than normal.

Massif 是一个堆分析器。它通过获取程序堆的定期快照来执行详细的堆分析。它生成一个图表,显示随时间的堆使用情况,包括有关程序的哪些部分负责最多内存分配的信息。该图由文本或 HTML 文件补充,其中包含更多信息,用于确定分配最多内存的位置。Massif 运行程序的速度比正常情况慢 20 倍。

As explained in the valgrind documentation, you need to run the program through valgrind:

valgrind 文档中所述,您需要通过 valgrind 运行程序:

valgrind --tool=massif <executable> <arguments>

Massif writes a dump of memory usage snapshots (e.g. massif.out.12345). These provide, (1) a timeline of memory usage, (2) for each snapshot, a record of where in your program memory was allocated. A great graphical tool for analyzing these files is massif-visualizer. But I found ms_print, a simple text-based tool shipped with valgrind, to be of great help already.

Massif 写入内存使用快照的转储(例如massif.out.12345)。这些提供,(1) 内存使用的时间线,(2) 对于每个快照,记录程序内存中的分配位置。分析这些文件的一个很好的图形工具是massif-visualizer。但我发现ms_printvalgrind 附带的一个简单的基于文本的工具已经很有帮助。

To find memory leaks, use the (default) memchecktool of valgrind.

要查找内存泄漏,请使用memcheckvalgrind的(默认)工具。

回答by DustinB

Hard to tell for sure, but here are two "close" things that can help.

很难确定,但这里有两个“接近”的事情可以提供帮助。

$ ps aux 

will give you Virtual Size (VSZ)

会给你虚拟尺寸(VSZ)

You can also get detailed stats from /proc file-system by going to /proc/$pid/status

您还可以通过转至 /proc 文件系统获取详细统计信息 /proc/$pid/status

The most important is the VmSize, which should be close to what ps auxgives.

最重要的是 VmSize,它应该接近ps aux给出的值。

/proc/19420$ cat status
Name:   firefox
State:  S (sleeping)
Tgid:   19420
Pid:    19420
PPid:   1
TracerPid:  0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 256
Groups: 4 6 20 24 25 29 30 44 46 107 109 115 124 1000 
VmPeak:   222956 kB
VmSize:   212520 kB
VmLck:         0 kB
VmHWM:    127912 kB
VmRSS:    118768 kB
VmData:   170180 kB
VmStk:       228 kB
VmExe:        28 kB
VmLib:     35424 kB
VmPTE:       184 kB
Threads:    8
SigQ:   0/16382
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000020001000
SigCgt: 000000018000442f
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
Cpus_allowed:   03
Mems_allowed:   1
voluntary_ctxt_switches:    63422
nonvoluntary_ctxt_switches: 7171

回答by DarenW

Get valgrind. give it your program to run, and it'll tell you plenty about its memory usage.

获取 valgrind。让它运行你的程序,它会告诉你很多关于它的内存使用情况。

This would apply only for the case of a program that runs for some time and stops. I don't know if valgrind can get its hands on an already-running process or shouldn't-stop processes such as daemons.

这仅适用于程序运行一段时间后停止的情况。我不知道 valgrind 是否可以处理一个已经在运行的进程,或者不应该停止诸如守护进程之类的进程。

回答by Bash

There is no easy way to calculate this. But some people have tried to get some good answers:

没有简单的方法来计算这个。但有些人试图得到一些好的答案:

回答by Dan

Another vote for valgrindhere, but I would like to add that you can use a tool like Alleyoopto help you interpret the results generated by valgrind.

在这里再次为valgrind投票,但我想补充一点,您可以使用像Alleyoop这样的工具来帮助您解释 valgrind 生成的结果。

I use the two tools all the time and always have lean, non-leaky code to proudly show for it ;)

我一直在使用这两个工具,并且总是有精简、无泄漏的代码来自豪地展示它;)

回答by Dprado

There isn't a single answer for this because you can't pin point precisely the amount of memory a process uses. Most processes under linux use shared libraries. For instance, let's say you want to calculate memory usage for the 'ls' process. Do you count only the memory used by the executable 'ls' ( if you could isolate it) ? How about libc? Or all these other libs that are required to run 'ls'?

对此没有唯一的答案,因为您无法准确指出进程使用的内存量。linux下的大多数进程都使用共享库。例如,假设您要计算 'ls' 进程的内存使用情况。您是否只计算可执行文件 'ls' 使用的内存(如果可以隔离的话)?libc呢?或者运行“ls”所需的所有其他库?

linux-gate.so.1 =>  (0x00ccb000)
librt.so.1 => /lib/librt.so.1 (0x06bc7000)
libacl.so.1 => /lib/libacl.so.1 (0x00230000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00162000)
libc.so.6 => /lib/libc.so.6 (0x00b40000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00cb4000)
/lib/ld-linux.so.2 (0x00b1d000)
libattr.so.1 => /lib/libattr.so.1 (0x00229000)
libdl.so.2 => /lib/libdl.so.2 (0x00cae000)
libsepol.so.1 => /lib/libsepol.so.1 (0x0011a000)

You could argue that they are shared by other processes, but 'ls' can't be run on the system without them being loaded.

您可能会争辩说它们被其他进程共享,但是 'ls' 不能在没有加载它们的情况下在系统上运行。

Also, if you need to know how much memory a process needs in order to do capacity planning, you have to calculate how much each additional copy of the process uses. I think /proc/PID/status might give you enough info of the memory usage AT a single time. On the other hand, valgrind will give you a better profile of the memory usage throughout the lifetime of the program

此外,如果您需要知道进程需要多少内存才能进行容量规划,则必须计算进程的每个额外副本使用的内存量。我认为 /proc/PID/status 可能会一次性为您提供足够的内存使用信息。另一方面,valgrind 将为您提供整个程序生命周期内存使用情况的更好概况

回答by Paul Biggar

In recent versions of linux, use the smapssubsystem. For example, for a process with a PID of 1234:

在最新版本的 linux 中,使用smaps子系统。例如,对于 PID 为 1234 的进程:

cat /proc/1234/smaps

It will tell you exactly how much memory it is using at that time. More importantly, it will divide the memory into private and shared, so you can tell how much memory your instanceof the program is using, without including memory shared between multiple instances of the program.

它会告诉你当时它使用了多少内存。更重要的是,它将内存分为私有和共享内存,因此您可以知道您的程序实例使用了多少内存,而不包括程序多个实例之间共享的内存。

回答by juanjux

If you want something quicker than profiling with Valgrind and your kernel is older and you can't use smaps, a ps with the options to show the resident set of the process (with ps -o rss,command) can give you a quick and reasonable _aproximation_of the real amount of non-swapped memory being used.

如果您想要比使用 Valgrind 进行分析更快的东西,并且您的内核较旧并且您不能使用 smap,那么带有选项的 ps 可以显示进程的驻留集(with ps -o rss,command)可以为您提供快速合理_aproximation_的实际数量正在使用非交换内存。

回答by phoku

This is an excellent summary of the tools and problems: archive.org link

这是工具和问题的极好总结:archive.org 链接

I'll quote it, so that more devs will actually read it.

我会引用它,以便更多的开发人员真正阅读它。

If you want to analyse memory usage of the whole system or to thoroughly analyse memory usage of one application (not just its heap usage), use exmap. For whole system analysis, find processes with the highest effective usage, they take the most memory in practice, find processes with the highest writable usage, they create the most data (and therefore possibly leak or are very ineffective in their data usage). Select such application and analyse its mappings in the second listview. See exmap section for more details. Also use xrestopto check high usage of X resources, especially if the process of the X server takes a lot of memory. See xrestop section for details.

If you want to detect leaks, use valgrindor possibly kmtrace.

If you want to analyse heap (malloc etc.) usage of an application, either run it in memprofor with kmtrace, profile the application and search the function call tree for biggest allocations. See their sections for more details.

如果要分析整个系统的内存使用情况或彻底分析一个应用程序的内存使用情况(而不仅仅是其堆使用情况),请使用exmap。对于整个系统分析,找到有效使用率最高的进程,它们在实践中占用的内存最多,找到可写使用率最高的进程,它们创建的数据最多(因此可能会泄漏或在数据使用方面非常低效)。选择此类应用程序并在第二个列表视图中分析其映射。有关更多详细信息,请参阅 exmap 部分。还可以使用xrestop来检查 X 资源的高使用率,尤其是在 X 服务器的进程占用大量内存的情况下。有关详细信息,请参阅 xrestop 部分。

如果要检测泄漏,请使用valgrindkmtrace

如果要分析应用程序的堆(malloc 等)使用情况,请在memprof或使用kmtrace运行它,分析应用程序并搜索函数调用树以获取最大分配。有关更多详细信息,请参阅他们的部分。

回答by holmes

Valgrindcan show detailed information but it slows downthe target application significantly, and most of the time it changes the behavior of the app.
Exmapwas something I didn't know yet, but it seems that you need a kernel moduleto get the information, which can be an obstacle.

Valgrind可以显示详细信息,但它显着降低目标应用程序的速度,并且大多数时候它会改变应用程序的行为。
Exmap是我还不知道的东西,但似乎您需要一个内核模块来获取信息,这可能是一个障碍。

I assume what everyone wants to know WRT "memory usage" is the following...
In linux, the amount of physical memory a single process might use can be roughly divided into following categories.

我假设每个人都想知道WRT“内存使用情况”如下...
在linux中,单个进程可能使用的物理内存量大致可以分为以下几类。

  • M.a anonymous mapped memory

    • .p private
      • .d dirty == malloc/mmapped heap and stack allocated and written memory
      • .c clean == malloc/mmapped heap and stack memory once allocated, written, then freed, but not reclaimed yet
    • .s shared
      • .d dirty == malloc/mmaped heap could get copy-on-write and shared among processes(edited)
      • .c clean == malloc/mmaped heap could get copy-on-write and shared among processes(edited)
  • M.n named mapped memory

    • .p private
      • .d dirty == file mmapped written memory private
      • .c clean == mapped program/library text private mapped
    • .s shared
      • .d dirty == file mmapped written memory shared
      • .c clean == mapped library text shared mapped
  • 匿名映射内存

    • .p 私人
      • .d 脏 == malloc/mmapped 堆和栈分配和写入的内存
      • .c clean == malloc/mmapped 堆和堆栈内存一旦分配、写入、然后释放,但尚未回收
    • .s 共享
      • .d 脏 == malloc/mmaped 堆可以在写时复制并在进程之间共享(已编辑)
      • .c clean == malloc/mmaped heap 可以在写时复制并在进程之间共享(已编辑)
  • Mn 命名映射内存

    • .p 私人
      • .d 脏 == 文件 mmapped 写入内存私有
      • .c clean == 映射的程序/库文本私有映射
    • .s 共享
      • .d 脏 == 文件 mmapped 写入内存共享
      • .c clean == 映射库文本共享映射

Utility included in Android called showmapis quite useful

Android 中包含的名为showmap 的实用程序非常有用

virtual                    shared   shared   private  private
size     RSS      PSS      clean    dirty    clean    dirty    object
-------- -------- -------- -------- -------- -------- -------- ------------------------------
       4        0        0        0        0        0        0 0:00 0                  [vsyscall]
       4        4        0        4        0        0        0                         [vdso]
      88       28       28        0        0        4       24                         [stack]
      12       12       12        0        0        0       12 7909                    /lib/ld-2.11.1.so
      12        4        4        0        0        0        4 89529                   /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
      28        0        0        0        0        0        0 86661                   /usr/lib/gconv/gconv-modules.cache
       4        0        0        0        0        0        0 87660                   /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
       4        0        0        0        0        0        0 89528                   /usr/lib/locale/en_US.utf8/LC_TELEPHONE
       4        0        0        0        0        0        0 89527                   /usr/lib/locale/en_US.utf8/LC_ADDRESS
       4        0        0        0        0        0        0 87717                   /usr/lib/locale/en_US.utf8/LC_NAME
       4        0        0        0        0        0        0 87873                   /usr/lib/locale/en_US.utf8/LC_PAPER
       4        0        0        0        0        0        0 13879                   /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
       4        0        0        0        0        0        0 89526                   /usr/lib/locale/en_US.utf8/LC_MONETARY
       4        0        0        0        0        0        0 89525                   /usr/lib/locale/en_US.utf8/LC_TIME
       4        0        0        0        0        0        0 11378                   /usr/lib/locale/en_US.utf8/LC_NUMERIC
    1156        8        8        0        0        4        4 11372                   /usr/lib/locale/en_US.utf8/LC_COLLATE
     252        0        0        0        0        0        0 11321                   /usr/lib/locale/en_US.utf8/LC_CTYPE
     128       52        1       52        0        0        0 7909                    /lib/ld-2.11.1.so
    2316       32       11       24        0        0        8 7986                    /lib/libncurses.so.5.7
    2064        8        4        4        0        0        4 7947                    /lib/libdl-2.11.1.so
    3596      472       46      440        0        4       28 7933                    /lib/libc-2.11.1.so
    2084        4        0        4        0        0        0 7995                    /lib/libnss_compat-2.11.1.so
    2152        4        0        4        0        0        0 7993                    /lib/libnsl-2.11.1.so
    2092        0        0        0        0        0        0 8009                    /lib/libnss_nis-2.11.1.so
    2100        0        0        0        0        0        0 7999                    /lib/libnss_files-2.11.1.so
    3752     2736     2736        0        0      864     1872                         [heap]
      24       24       24        0        0        0       24 [anon]
     916      616      131      584        0        0       32                         /bin/bash
-------- -------- -------- -------- -------- -------- -------- ------------------------------
   22816     4004     3005     1116        0      876     2012 TOTAL