Skip to content

Instantly share code, notes, and snippets.

@croepha
Last active July 24, 2018 02:46
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 croepha/a12080ff844388431d995c961a1ebd0a to your computer and use it in GitHub Desktop.
Save croepha/a12080ff844388431d995c961a1ebd0a to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <assert.h>
#define acount(m_a) (sizeof m_a/sizeof m_a[0])
typedef unsigned long long u64;
typedef int s32;
static_assert(sizeof(s32) == 4);
const s32 READ_BUFFER_SIZE = 4096;
const s32 BUCKET_COUNT = 2;
const s32 CPU_COUNT = 8;
// Assign specific cores to buckets
const s32 logical_core_bucket_assignments[] = {
0, 1, 0, 1, 0, 1, 0, 1,
//0 1 2 3 4 5 6 7
};
namespace TIME_TYPES { enum {
user, nice, system, idle,
_COUNT
};}
u64 cpu_times[CPU_COUNT][TIME_TYPES::_COUNT];
char read_buffer[READ_BUFFER_SIZE];
char* read_buffer_end = read_buffer + READ_BUFFER_SIZE;
inline static int scan_cmp(char*&c, char*to) {
while (*to && *c == *to) { c++; to++; }
return !*to;
}
inline static bool scan_decimal(char*&c, u64&v) {
v = 0;
bool is_valid = false;
for(;;) {
if (*c < '0' || *c > '9') break;
v *= 10;
v += *c - '0';
is_valid = true;
c++;
}
return is_valid;
}
inline static void scan_until(char*&c, char to) {
while (*c && *c != to) { c++; }
}
const int sleep_ms = 500;
int main() {
s32 total_time = (sleep_ms * sysconf(_SC_CLK_TCK)) / 1000;
s32 total[BUCKET_COUNT] = {};
for (int i = 0; i<CPU_COUNT; i++) {
total[logical_core_bucket_assignments[i]] += total_time;
}
auto fd = open("/proc/stat", O_RDONLY);
for (;;) {
auto byte_count = read(fd, read_buffer, READ_BUFFER_SIZE - 1);
assert(byte_count>=0);
char*c = read_buffer;
printf("\033[1;1H\033[2J"); //clear screen
u64 delta[BUCKET_COUNT][TIME_TYPES::_COUNT] = {};
for (;;) {
u64 cpu_logical_id;
if (!scan_cmp(c, "cpu")) break;
if (!scan_decimal(c, cpu_logical_id)) goto read_rest_of_line; // the "all cpus" entry...
if (cpu_logical_id < 0 || cpu_logical_id >= acount(logical_core_bucket_assignments))
exit(-__LINE__);
{
u64 times[TIME_TYPES::_COUNT];
if (!scan_cmp(c, " ") ) abort();
if (!scan_decimal(c, times[TIME_TYPES::user]) ) abort();
if (!scan_cmp(c, " ") ) abort();
if (!scan_decimal(c, times[TIME_TYPES::nice]) ) abort();
if (!scan_cmp(c, " ") ) abort();
if (!scan_decimal(c, times[TIME_TYPES::system])) abort();
if (!scan_cmp(c, " ") ) abort();
if (!scan_decimal(c, times[TIME_TYPES::idle]) ) abort();
for (int i=0;i<TIME_TYPES::_COUNT;i++) {
int bucket_id = logical_core_bucket_assignments[cpu_logical_id];
if (cpu_times[cpu_logical_id][i]) {
delta[bucket_id][i] += times[i] - cpu_times[cpu_logical_id][i];
}
cpu_times[cpu_logical_id][i] = times[i];
}
}
read_rest_of_line:
scan_until(c, '\n');
c++;
}
for (int bi=0; bi<BUCKET_COUNT; bi++) {
int total_width = 50;
int widths[TIME_TYPES::_COUNT];
float total_so_far = 0;
for (int i=0;i<TIME_TYPES::_COUNT;i++) {
total_so_far = total_so_far + ((float)delta[bi][i] *(float)total_width) / (float)total[bi];
widths[i] = total_so_far;
}
printf("bucket:%d user:%llu nice:%llu system:%llu idle:%lld total:%d\n",
bi,
delta[bi][TIME_TYPES::user ],
delta[bi][TIME_TYPES::nice ],
delta[bi][TIME_TYPES::system],
delta[bi][TIME_TYPES::idle ],
total[bi]);
char line_buf[1024];
for (int i=0;i<total_width;i++) {
// user, nice, system, idle,
line_buf[i] = '?';
if (i<widths[TIME_TYPES::idle ]) line_buf[i] = ' ';
if (i<widths[TIME_TYPES::system]) line_buf[i] = 'S';
if (i<widths[TIME_TYPES::nice ]) line_buf[i] = 'N';
if (i<widths[TIME_TYPES::user ]) line_buf[i] = 'U';
}
line_buf[total_width] = 0;
printf("%s\n", line_buf);
}
lseek(fd, 0, SEEK_SET);
usleep(sleep_ms * 1000);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment