0

I am trying to get the memory consumed by an algorithm, so I have created a group of functions that would stop the execution in periods of 10 milliseconds to let me read the memory using the getrusage() function. The idea is to set a timer that will raise an alarm signal to the process which will be received by a handler medir_memoria().

However, the program stops in the middle with this message:

[1]    3267 alarm    ./memory_test

The code for reading the memory is:

#include "../include/rastreador_memoria.h"

#if defined(__linux__) || defined(__APPLE__) || (defined(__unix__) && !defined(_WIN32))

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
#include <sys/resource.h>

static long max_data_size;
static long max_stack_size;

void medir_memoria (int sig)
{
    struct rusage info_memoria;

    if (getrusage(RUSAGE_SELF, &info_memoria) < 0)
    {
        perror("Not reading memory");
    }

    max_data_size = (info_memoria.ru_idrss > max_data_size) ? info_memoria.ru_idrss : max_data_size;
    max_stack_size = (info_memoria.ru_isrss > max_stack_size) ? info_memoria.ru_isrss : max_stack_size;

    signal(SIGALRM, medir_memoria);
}

void rastrear_memoria ()
{
    struct itimerval t;

    t.it_interval.tv_sec = 0;
    t.it_interval.tv_usec = 10;
    t.it_value.tv_sec = 0;
    t.it_value.tv_usec = 10;

    max_data_size = 0;
    max_stack_size = 0;

    setitimer(ITIMER_REAL, &t,0);
    signal(SIGALRM, medir_memoria);
}

void detener_rastreo ()
{
    signal(SIGALRM, SIG_DFL);

    printf("Data: %ld\nStack: %ld\n", max_data_size, max_stack_size);
}

#else

#endif

The main() function works calling all of them in this order:

  1. rastrear_memoria()
  2. Function of the algorithm I am testing
  3. detener_rastreo()

How can I solve this? What does that alarm message mean?

Jaime_mc2
  • 673
  • 5
  • 18

1 Answers1

2

First, setting an itimer to ring every 10 µs is optimistic, since ten microseconds is really a small interval of time. Try with 500 µs (or perhaps even 20 milliseconds, i.e. 20000 µs) instead of 10 µs first.

stop the execution in periods of 10 milliseconds

You have coded for a period of 10 microseconds, not milliseconds!

Then, you should exchange the two lines and code:

signal(SIGALRM, medir_memoria);
setitimer(ITIMER_REAL, &t,0);

so that a signal handler is set before the first itimer rings.

I guess your first itimer rings before the signal handler was installed. Read carefully signal(7) and time(7). The default handling of SIGALRM is termination.

BTW, a better way to measure the time used by some function is clock_gettime(2) or clock(3). Thanks to vdso(7) tricks, clock_gettime is able to get some clock in less than 50 nanoseconds on my i5-4690S desktop computer.

trying to get the memory consumed

You could consider using proc(5) e.g. opening, reading, and closing quickly /proc/self/status or /proc/self/statm etc....

(I guess you are on Linux)

BTW, your measurements will disappoint you: notice that quite often free(3) don't release memory to the kernel (thru munmap(2)...) but simply mark & manage that zone to be reusable by future malloc(3). You might consider mallinfo(3) or malloc_info(3) but notice that it is not async-signal-safe so cannot be called from inside a signal handler.

(I tend to believe that your approach is deeply flawed)

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547