zxjcarrot
zxjcarrot

Reputation: 1

how can i get the max memory usage of a child process after its execution accurately?

I have written a program which is used to monitoring child processes' resources. I used wait4 function's fourth argument to get child processes' CPU usage, which works fine. But i could use that to get memory usage, it looks different from the output of "ps". I also tried parsing /proc/pid/status, but sometimes it's not accurate, for some child process is too quick to parse. can anybody give me some advice or solution? Thanks a lot.

Upvotes: 0

Views: 895

Answers (1)

ash
ash

Reputation: 5165

Once the process terminates, even though the process entry still exists in the kernel, all of the resources for the process are released by the kernel. So, I would not expect to be able to read the memory size of the process from /proc.

In addition, there's no "maximum memory used" statistic for the process.

The only ways I can think to determine the maximum amount of memory for a process are the following:

  1. Periodically sample the process state while it's executing and grab the current memory usage,
  2. Use strace to capture all of the system calls made by the process and process this to determine just how much memory the process used, or
  3. Use a shared library to intercept the memory-allocation system calls as they are made by the process, capture the details, and find a way to report

I would probably go with (1) unless very high accuracy is absolutely needed.

There may be profiling or statistics tools to help in this task, but I'm not aware of any.


Using Strace

Here's a program that illustrates the use of strace for this purpose:

allocit.c

#include <stdio.h>
#include <stdlib.h>

int main ()
{
        int     cur;

        cur = 0;
        while ( cur < 1000 )
        {
                malloc(1024);
                cur++;
        }

        return  0;
}

Running this with strace (strace ./allocit) gets output like this:

execve("./allocit", ["./allocit"], [/* 49 vars */]) = 0
brk(0)                                  = 0x1b991000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae49dccd000
uname({sys="Linux", node="fearless.office.tmcs", ...}) = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/home/jdoe/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/home/jdoe/lib/tls/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/home/jdoe/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/home/jdoe/lib/tls", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/home/jdoe/lib/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/home/jdoe/lib/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/home/jdoe/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/home/jdoe/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/software/ticketmaster/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/software/ticketmaster/lib/tls/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/software/ticketmaster/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/software/ticketmaster/lib/tls", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/software/ticketmaster/lib/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/software/ticketmaster/lib/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/software/ticketmaster/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/software/ticketmaster/lib", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/usr/lib/oracle/11.2/client64/lib/tls/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib/oracle/11.2/client64/lib/tls/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/usr/lib/oracle/11.2/client64/lib/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib/oracle/11.2/client64/lib/tls", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/usr/lib/oracle/11.2/client64/lib/x86_64/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib/oracle/11.2/client64/lib/x86_64", 0x7fff896b2900) = -1 ENOENT (No such file or directory)
open("/usr/lib/oracle/11.2/client64/lib/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
stat("/usr/lib/oracle/11.2/client64/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=123338, ...}) = 0
mmap(NULL, 123338, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2ae49dcce000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\332!\2359\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1717800, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae49dced000
mmap(0x399d200000, 3498328, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x399d200000
mprotect(0x399d34e000, 2093056, PROT_NONE) = 0
mmap(0x399d54d000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14d000) = 0x399d54d000
mmap(0x399d552000, 16728, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x399d552000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2ae49dcee000
arch_prctl(ARCH_SET_FS, 0x2ae49dcee210) = 0
mprotect(0x399d54d000, 16384, PROT_READ) = 0
mprotect(0x399d01b000, 4096, PROT_READ) = 0
munmap(0x2ae49dcce000, 123338)          = 0
brk(0)                                  = 0x1b991000
brk(0x1b9b2000)                         = 0x1b9b2000
brk(0x1b9d3000)                         = 0x1b9d3000
brk(0x1b9f4000)                         = 0x1b9f4000
brk(0x1ba15000)                         = 0x1ba15000
brk(0x1ba36000)                         = 0x1ba36000
brk(0x1ba57000)                         = 0x1ba57000
brk(0x1ba78000)                         = 0x1ba78000
brk(0x1ba99000)                         = 0x1ba99000
exit_group(0)                           = ?

Note all of the brk() calls used to expand the heap.

Upvotes: 2

Related Questions