//$Id: perf.C,v 1.1 2012/04/03 10:49:59 zjcao Exp $ #include "perf.h" // initialize staic members size_t perf::mem_peak = 0; size_t perf::mem_current = 0; int perf::sampling_interval = 200; bool perf::have_statm = false; char perf::statm[40] = " "; struct itimerval perf::new_it; struct itimerval perf::old; struct sigaction perf::sa; struct sigaction perf::old_sa; perf::perf() { int fd; sprintf(statm, "/proc/%d/statm", (int)getpid()); if ((fd = open(statm, O_RDONLY)) != -1) { have_statm = true; close(fd); } if (sampling_interval > 0) { /* setup timer to sample memory usage */ sa.sa_handler = &perf::sample_mem_usage; sigemptyset(&sa.sa_mask); /*sigfillset (&sa.sa_mask);*/ sa.sa_flags = SA_RESTART; if (sigaction(TimerSignal, &sa, &old_sa)) perror("sigaction 0"); new_it.it_value.tv_sec = sampling_interval / 1000; new_it.it_value.tv_usec = (sampling_interval % 1000) * 1000; new_it.it_interval = new_it.it_value; if (setitimer(TimerType, &new_it, &old)) perror("setitimer 0"); } } perf::~perf() { } void perf::sample_mem_usage(int dummy) { int fd; struct rusage RU; size_t mem; static bool locked = false; if (locked) return; locked = true; /* TODO: configure checks for different systems */ /* first, try /proc/pid/statm for Linux systems */ if (have_statm && (fd = open(statm, O_RDONLY)) != -1) { int rsspages; static char buffer[256]; char *p = buffer; /* see linux-2.6.15/Documentation/filesystems/proc.txt */ rsspages = read(fd, buffer, sizeof(buffer) - 1); close(fd); buffer[rsspages] = '\0'; strtol(p, &p, 10); /* first number () */ rsspages = strtol(p, &p, 10); /* second number */ mem = (size_t)rsspages * (size_t)getpagesize(); } else { /* next, try getrusage() */ if (getrusage(RUSAGE_SELF, &RU)) cout << "perf::sample_mem_usage calling getrusage fail" << endl; else mem = RU.ru_maxrss * (size_t)1024; /*mem = RU.ru_maxrss * getpagesize();*/ } if (mem > mem_peak) mem_peak = mem; mem_current = mem; locked = false; } size_t perf::MemoryUsage(size_t *current_min, size_t *current_avg, size_t *current_max, size_t *peak_min, size_t *peak_avg, size_t *peak_max, int nprocs) { sample_mem_usage(0); double a[2][3], b[2][3]; a[0][0] = a[0][1] = a[0][2] = mem_current; a[1][0] = a[1][1] = a[1][2] = mem_peak; MPI_Allreduce(a, b, 6, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); b[0][1] /= nprocs; b[1][1] /= nprocs; if (current_min != NULL) *current_min = (size_t)(b[0][0] + 0.5); if (current_avg != NULL) *current_avg = (size_t)(b[0][1] + 0.5); if (current_max != NULL) *current_max = (size_t)(b[0][2] + 0.5); if (peak_min != NULL) *peak_min = (size_t)(b[1][0] + 0.5); if (peak_avg != NULL) *peak_avg = (size_t)(b[1][1] + 0.5); if (peak_max != NULL) *peak_max = (size_t)(b[1][2] + 0.5); return (size_t)b[0][2]; /* return max(mem_current) */ }