Last active
January 7, 2017 12:14
-
-
Save lcpz/277e6cb8468d6d1bf958 to your computer and use it in GitHub Desktop.
A simple program for monitoring lain performances - https://github.com/copycat-killer/lain/issues/114
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
compile: gcc -o ticks ticks.c | |
run: ./ticks $(pgrep awesome) 20 3 | |
This makes 3 measurements of each 20 seconds | |
Best used with short timeouts in the widgets and everything else idling. | |
*/ | |
//Last modified: 18/11/12 19:13:35(CET) by Fabian Holler | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <limits.h> | |
struct pstat { | |
long unsigned int utime_ticks; | |
long int cutime_ticks; | |
long unsigned int stime_ticks; | |
long int cstime_ticks; | |
long unsigned int vsize; // virtual memory size in bytes | |
long unsigned int rss; //Resident Set Size in bytes | |
long unsigned int cpu_total_time; | |
}; | |
/* | |
* read /proc data into the passed struct pstat | |
* returns 0 on success, -1 on error | |
*/ | |
int get_usage(const pid_t pid, struct pstat* result) { | |
//convert pid to string | |
char pid_s[20]; | |
snprintf(pid_s, sizeof(pid_s), "%d", pid); | |
char stat_filepath[30] = "/proc/"; strncat(stat_filepath, pid_s, | |
sizeof(stat_filepath) - strlen(stat_filepath) -1); | |
strncat(stat_filepath, "/stat", sizeof(stat_filepath) - | |
strlen(stat_filepath) -1); | |
FILE *fpstat = fopen(stat_filepath, "r"); | |
if (fpstat == NULL) { | |
perror("FOPEN ERROR "); | |
return -1; | |
} | |
FILE *fstat = fopen("/proc/stat", "r"); | |
if (fstat == NULL) { | |
perror("FOPEN ERROR "); | |
fclose(fstat); | |
return -1; | |
} | |
//read values from /proc/pid/stat | |
bzero(result, sizeof(struct pstat)); | |
long int rss; | |
if (fscanf(fpstat, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu" | |
"%lu %ld %ld %*d %*d %*d %*d %*u %lu %ld", | |
&result->utime_ticks, &result->stime_ticks, | |
&result->cutime_ticks, &result->cstime_ticks, &result->vsize, | |
&rss) == EOF) { | |
fclose(fpstat); | |
return -1; | |
} | |
fclose(fpstat); | |
result->rss = rss * getpagesize(); | |
//read+calc cpu total time from /proc/stat | |
long unsigned int cpu_time[10]; | |
bzero(cpu_time, sizeof(cpu_time)); | |
if (fscanf(fstat, "%*s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", | |
&cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3], | |
&cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7], | |
&cpu_time[8], &cpu_time[9]) == EOF) { | |
fclose(fstat); | |
return -1; | |
} | |
fclose(fstat); | |
for(int i=0; i < 10;i++) | |
result->cpu_total_time += cpu_time[i]; | |
return 0; | |
} | |
/* | |
* calculates the elapsed CPU usage between 2 measuring points. in percent | |
*/ | |
void calc_cpu_usage_pct(const struct pstat* cur_usage, | |
const struct pstat* last_usage, | |
double* ucpu_usage, double* scpu_usage) | |
{ | |
const long unsigned int total_time_diff = cur_usage->cpu_total_time - | |
last_usage->cpu_total_time; | |
*ucpu_usage = 100 * (((cur_usage->utime_ticks + cur_usage->cutime_ticks) | |
- (last_usage->utime_ticks + last_usage->cutime_ticks)) | |
/ (double) total_time_diff); | |
*scpu_usage = 100 * ((((cur_usage->stime_ticks + cur_usage->cstime_ticks) | |
- (last_usage->stime_ticks + last_usage->cstime_ticks))) / | |
(double) total_time_diff); | |
} | |
/* | |
* calculates the elapsed CPU usage between 2 measuring points in ticks | |
*/ | |
void calc_cpu_usage(const struct pstat* cur_usage, | |
const struct pstat* last_usage, | |
long unsigned int* ucpu_usage, | |
long unsigned int* scpu_usage) | |
{ | |
*ucpu_usage = (cur_usage->utime_ticks + cur_usage->cutime_ticks) - | |
(last_usage->utime_ticks + last_usage->cutime_ticks); | |
*scpu_usage = (cur_usage->stime_ticks + cur_usage->cstime_ticks) - | |
(last_usage->stime_ticks + last_usage->cstime_ticks); | |
} | |
int main(int argc, char **argv) { | |
pid_t pid = 1; | |
int slp = 10; | |
int it = 1; | |
if (argc >= 2) { | |
pid = atoi(argv[1]); | |
} | |
if (argc >= 3) { | |
slp = atoi(argv[2]); | |
} | |
if (argc >= 4) { | |
it = atoi(argv[3]); | |
} | |
if (it == -1) it = INT_MAX; | |
for (int i=0; i<it; i++) { | |
struct pstat stat1, stat2; | |
long unsigned int user_ticks, system_ticks; | |
double user_pct, system_pct; | |
get_usage(pid, &stat1); | |
sleep(slp); | |
get_usage(pid, &stat2); | |
calc_cpu_usage(&stat2, &stat1, &user_ticks, &system_ticks); | |
calc_cpu_usage_pct(&stat2, &stat1, &user_pct, &system_pct); | |
printf(" Ticks:\tuser = %lu\tsystem = %lu\tsum = %lu\n", | |
user_ticks, system_ticks, user_ticks + system_ticks); | |
printf("Percent:\tuser = %.1f\tsystem = %.1f\tsum = %.1f\n\n", | |
user_pct, system_pct, user_pct + system_pct); | |
} | |
return (0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment