Skip to content

Instantly share code, notes, and snippets.

@lcpz
Last active January 7, 2017 12:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lcpz/277e6cb8468d6d1bf958 to your computer and use it in GitHub Desktop.
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
/*
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