1

I have to make a tool like those 'online judges', to compile and execute c/cpp code and return some results, but also measure if it exceeds time limit or a memory limit.

I found multiple linux commands that use a process's PID, and i was able to get the pid of the process after i start the executable, but the process would finish before those linux commands that read memory usage, and so it would throw an error.

I also found valgrind, but it takes too much time to finish.

Is there a way to start an executable resultet from a given c/cpp file, and make it not end until i tell it to, so that i have time to read its memory usage???

A bash/cpp/c solution thkx.

alex4482
  • 7
  • 4
  • If (slightly) modifying your C programs is an option, perhaps you could [use a SIGINT handler](https://stackoverflow.com/a/19059462/1256234)? – Andy J May 15 '22 at 14:02
  • Do you want to enforce that program is not exceeding a given memory limit? or do you want to measure the exact maximum memory usage? The first one is a much simpler problem, the second one is more complex (even with non-intrusive approach) as it also depends on sampling (how often you measure and what metric) – Michail Alexakis May 15 '22 at 18:29
  • @AndyJ i dont think modifying the c script is an option:( – alex4482 May 15 '22 at 20:49
  • @MichailAlexakis first variant. If the program ends up exceding a limit memory, to return an error message. – alex4482 May 15 '22 at 20:50

3 Answers3

1

If only concern is that a memory limit is not exceeded, then, instead of reading the peak memory usage, it is simpler to run the program into a properly constraint CGroup.

Both options below, use the same underlying mechanism (CGroups).

Let's say your program is ./a.out.

option 1 (simpler): Run a container with memory limit

This option needs docker to be installed.

Run into a temporary container (e.g. based on busybox):

docker run --rm -it -v $PWD/:/work -w /work --memory=64m busybox ./a.out 

option 2: Create a custom cgroup and run process into it

This option requires cgroup-tools must be installed (in Debian-based systems, maybe named differently in other distributions).

Create a cgroup (as supersuser) for a normal user. For example, create a cgroup test1 for resource controller memory. This group is administered by user user1 (so user1 can both set limits (-a) and run tasks (-t) inside the cgroup):

sudo cgcreate -a user1:user1 -t user1:user1 -g memory:test1

As a normal user user1 set some limits using the /sys/fs/cgroup hierarchy:

echo 64m > /sys/fs/cgroup/memory/test1/memory.limit_in_bytes

Run a program inside a cgroup using cgexec:

cgexec -g memory:test1 ./a.out
Michail Alexakis
  • 1,405
  • 15
  • 14
  • I forgot to mention i actually use docker. But i just saw that the minimum limit docker allows is 6mb. And i need to somehow set it to 2. Is there a way to set this with docker? Or do i have to use the second option – alex4482 May 16 '22 at 08:52
  • I read docker needs 6mb to start correctly, and that is why i cant set the limit lower. But can i maybe constantly use 4mb and then let the cpp script use the other 2mb?and if it uses it much, it would give error – alex4482 May 16 '22 at 09:01
  • Yes, you cannot set such a low limit on memory of `docker-run`, it used to be 4M but now is 6M (see also [this issue](https://github.com/moby/moby/issues/41167)). You can try your workaround with allocating 4M in advance (but is rather fragile i think). You can also try the 2nd option with `cgexec` which does not have the above limitations. – Michail Alexakis May 16 '22 at 09:26
  • are you talking about ram or disk usage? – alex4482 May 19 '22 at 16:40
  • @alex4482, about memory usage – Michail Alexakis May 19 '22 at 18:58
  • memory usage refers to how much memory it writes on disk, or ram memory? I may have misunderstood this term during my research for this issue. – alex4482 May 20 '22 at 09:57
  • @alex4482, memory (unless you do swapping to disk) refers to RAM – Michail Alexakis May 20 '22 at 10:04
1

Use the /usr/bin/time command with a custom output format for example:

/usr/bin/time -f "***** Maximum RSS = %M kB *****" COMMAND ARGS...

The last line of output will be your custom string containing the Maximum 'Resident Set Size'. Note, however, that RSS is not the same as total memory. Check here for an explanation: Wikipedia

Andrew Vickers
  • 2,504
  • 2
  • 10
  • 16
0

Have the C/C++ code send itself the STOP signal with a kill() function call right before it exits. This will freeze the process. You can then do whatever you need to in your script and then send the process the CONT signal to un-freeze it.

Andrew Vickers
  • 2,504
  • 2
  • 10
  • 16
  • The thing is: i cant modify the c/cpp script. Since that script is given to my api. I have another script that compiles the c/cpp script and executes it. Right now that script is writen in bash, but i can modify it to be in c/cpp if i find a solution in c/cpp. – alex4482 May 15 '22 at 20:31