57

time is a brilliant command if you want to figure out how much CPU time a given command takes.

I am looking for something similar that can measure the max RAM usage of the program and any children. Preferably it should distinguish between allocated memory that was used and unused. Maybe it could even give the median memory usage (so the memory usage you should expect when running for a long time).

So I would like to do:

rammeassure my_program my_args

and get output similar to:

Max memory allocated: 10233303 Bytes
Max memory used: 7233303 Bytes
Median memory allocation: 5233303 Bytes

I have looked at memusg https://gist.github.com/526585/590293d6527c91e48fcb08edb8de9fd6c88a6d82 but I regard that as somewhat a hack.

Ole Tange
  • 35,514

5 Answers5

41

time is a built-in of your shell. If you like time but need more information, try GNU time in verbose (-v) mode:

/usr/bin/time -v sleep 5               
    Command being timed: "sleep 5"
    User time (seconds): 0.00
    System time (seconds): 0.00
    Percent of CPU this job got: 0%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:05.00
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 2144
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 179
    Voluntary context switches: 2
    Involuntary context switches: 1
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

Search the package "time" or "gnutime" in your package manager.

heemayl
  • 56,300
  • 3
    Note that some information reported by GNU time could be inaccurate. E.g. under Ubuntu 10.04: The man page states 'The numbers are only as good as those returned by wait3(2)'. I.e. wait3 fills a structure which is described in getrusage(2): 'Not all fields are meaningful under Linux. [..]'. – maxschlepzig Aug 16 '11 at 19:49
  • 5
    For example on a test program that exactly allocates 10 MB (and touches each page) - GNU time reports a maxRSS of 42608 KiB - and tstime reports 10652 KiB. Again under Ubuntu 10.04. – maxschlepzig Aug 16 '11 at 19:58
  • I would have loved if it was this simple. On my Ubuntu machine I tried: /usr/bin/time -v perl -e '$a="x"x100000000;$b=$a.$a;sleep 10;'. top says it takes around 570 MB, but time says 2.3 GB. In practice that number is not usuable to me. – Ole Tange Aug 22 '11 at 11:56
  • The factor of 4 is fixed in GNU time 1.7 and thus works as expected. – Ole Tange Jan 30 '13 at 13:16
  • 1
    Important note: The "Maximum resident set size" only works since Linux 2.6.32. – Jan Hudec Nov 24 '14 at 14:45
  • I had to write command time -v <program> to get the right version of time. This was on Ubuntu 22.04 with bash. – Thorkil Værge Oct 18 '22 at 13:08
28

You can use tstime to measure the highwater memory usage (RSS and virtual) of a process.

For example:

$ tstime date       
Tue Aug 16 21:35:02 CEST 2011

Exit status: 0

pid: 31169 (date) started: Tue Aug 16 21:35:02 2011 real 0.017 s, user 0.000 s, sys 0.000s rss 888 kb, vm 9764 kb

It also supports a more easy to parse output mode (-t).

froque
  • 103
maxschlepzig
  • 57,532
  • I like it. It even did The Right Thing with ./tstime -t bash -c 'perl -e "\$a=\"x\"x100000000;\$b=\$a.\$a;\$b=\"\";\$a=\"\";sleep 10;"' – Ole Tange Aug 22 '11 at 12:00
  • 3
    "RAM usage by the process" isn't a well-defined value: If there are several instances of the same program running, they share the executable. Most programs share glibc (and other assorted libraries, they are called "shared" for something). Many daemons load configuration into memory and fork(2) children, who then share the configuration data. Then there is data in readahead/writebehind buffers managed by the kernel. And then there are services that are a herd of loosely coupled processes (think of your desktop environment and all its applets and background stuff). – vonbrand Jan 23 '13 at 16:05
  • @vonbrand, how the Linux-Kernel computes the RSS/VSS values is well-defined. – maxschlepzig Jan 23 '13 at 19:46
  • @maxschlepzig, it may well compute some random values, that doesn't mean they mean what you think they mean: The resident set is just the pages in the process' address space that are currently in memory. That is not the "memory used by this process", it includes whatever it is sharing. – vonbrand Jan 23 '13 at 19:50
  • @vonbrand Most use cases of measuring a process's memory usage will want to measure un-shared anonymous pages, which should be very predictable with the same input. – Vladimir Panteleev May 02 '15 at 12:56
  • What is "RSS" in this context? – Peter Mortensen Aug 30 '20 at 16:58
  • @PeterMortensen it's the resident set size – maxschlepzig Aug 30 '20 at 18:06
19

Maybe overkill, but I just found that valgrind has a nice tool named massif. I tested it on xterm:

valgrind --trace-children=yes --tool=massif xterm
ms_print massif.out.* | less

And you obtain a nice memory usage graph:

    MB
4.230^                     #                    :::::::  :::      @@:     ::: 
     |   @                 #:::@::@@:::::@::::::: :: : ::: :::::::@ ::::::: ::
     |   @               ::#:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::::@@:::::::::: #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
     |   @::: @ :: ::: : : #:: @: @ ::: :@: :: :: :: : ::: ::: : :@ :: : :: ::
   0 +----------------------------------------------------------------------->Mi
     0                                                                   292.4

along with overly detailed memory usage info. Details in the valgrind manual.

Programs will run about 20x slower though. Also, I ran some commands inside the xterm. Their memory footprint has been taken into account because the --trace-children=yes the option is there!

A.D.
  • 950
  • 2
    Th 20x speed penalty makes it unsuable for my situation. Otherwise very pretty graph! – Ole Tange Aug 22 '11 at 11:59
  • 1
    It looks like that, at least in the version 3.8.1 of valgrind that I am using, booleans are only accepted in the form "yes/no" and not "true/false". Mine complained! :-) – MakisH Feb 17 '16 at 01:09
6

Even though the topic is quite old, I want to share another project that emerged from the cgroups Linux kernel feature.

https://github.com/gsauthof/cgmemtime:

cgmemtime measures the high-water RSS+CACHE memory usage of a process and its descendant processes.

To be able to do so it puts the process into its own cgroup.

For example process A allocates 10 MiB and forks a child B that allocates 20 MiB and that forks a child C that allocates 30 MiB. All three processes share a time window where their allocations result in corresponding RSS (resident set size) memory usage.

The question now is: How much memory is actually used as a result of running A?

Answer: 60 MiB

cgmemtime is the tool to answer such questions.

3

Looks like tstime doesn't work anymore under non-root under Linux >=3.0. Here's a polling utility I wrote to hack around the issue: https://github.com/jhclark/memusg/blob/master/memusg

jhclark
  • 709
  • 1
    /usr/bin/time -v gives the correct output in newer versions. In older versions you just need to divide by 4 to get the correct amount. – Ole Tange Aug 30 '12 at 22:42
  • However, I don't think time -v supports peak vmemory size (only RSS). Can anyone confirm this on the latest version? – jhclark Sep 01 '12 at 00:48