Compare commits
4 commits
Author | SHA1 | Date | |
---|---|---|---|
Noah Swerhun | ba923d5d38 | ||
Noah Swerhun | 449568ee35 | ||
Noah Swerhun | 1b7ded5f8a | ||
Noah Swerhun | 8b4721dcf5 |
21
README.md
21
README.md
|
@ -1,14 +1,27 @@
|
||||||
# pss-total
|
# pss-total-waybar
|
||||||
sum proportional set size of every process for accurate memory usage statistics.
|
sum proportional set size of every process for accurate memory usage statistics.
|
||||||
In non-pretty mode, the number is given in kibibytes.
|
|
||||||
|
This version is for use with [waybar](https://github.com/Alexays/Waybar). It
|
||||||
|
outputs JSON that waybar can interpret using a
|
||||||
|
[custom module](https://github.com/Alexays/Waybar/wiki/Module:-Custom).
|
||||||
|
|
||||||
|
Here is an example configuration:
|
||||||
|
```json
|
||||||
|
"custom/pss-memory": {
|
||||||
|
"exec": "pss-total-waybar",
|
||||||
|
"return-type": "json",
|
||||||
|
"restart-interval": 3,
|
||||||
|
"format": "{} {icon}",
|
||||||
|
"format-icons": ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
Licensed under GPLv3.
|
Licensed under GPLv3.
|
||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
pss-total [OPTIONS]
|
pss-total-waybar [OPTIONS]
|
||||||
|
|
||||||
### Options
|
### Options
|
||||||
- `-p`, `--pretty`: format output using sensible units: KiB, MiB, or GiB.
|
|
||||||
- `-h`, `--help`: print this help message.
|
- `-h`, `--help`: print this help message.
|
||||||
|
|
||||||
|
|
||||||
|
|
48
build.ninja
48
build.ninja
|
@ -24,26 +24,6 @@ build $builddir/compile_commands.json: regen_compile_commands ngen.toml || $buil
|
||||||
build build.ninja: regen_ninjafile ngen.toml || $builddir/compile_commands.json
|
build build.ninja: regen_ninjafile ngen.toml || $builddir/compile_commands.json
|
||||||
pool = console
|
pool = console
|
||||||
|
|
||||||
# BEGIN TARGET debug
|
|
||||||
rule cc_debug
|
|
||||||
deps = gcc
|
|
||||||
depfile = $dep
|
|
||||||
command = cc -I. -fsanitize=address -O0 -g -MD -MF $dep -o $out -c $in
|
|
||||||
description = Building $in -> $out
|
|
||||||
rule link_debug
|
|
||||||
command = cc -fsanitize=address -o $out $in
|
|
||||||
description = Linking $out
|
|
||||||
|
|
||||||
build $builddir/debug/obj: mkdir
|
|
||||||
build $builddir/debug/dep: mkdir
|
|
||||||
|
|
||||||
build $builddir/debug/obj/src-main.c.o: cc_debug src/main.c
|
|
||||||
dep = $builddir/debug/dep/src-main.c.o.d
|
|
||||||
|
|
||||||
build $builddir/debug/pss-total: link_debug $builddir/debug/obj/src-main.c.o | || $builddir/debug/obj $builddir/debug/dep
|
|
||||||
build debug: phony $builddir/debug/pss-total
|
|
||||||
# END TARGET debug
|
|
||||||
|
|
||||||
# BEGIN TARGET release
|
# BEGIN TARGET release
|
||||||
rule cc_release
|
rule cc_release
|
||||||
deps = gcc
|
deps = gcc
|
||||||
|
@ -60,8 +40,8 @@ build $builddir/release/dep: mkdir
|
||||||
build $builddir/release/obj/src-main.c.o: cc_release src/main.c
|
build $builddir/release/obj/src-main.c.o: cc_release src/main.c
|
||||||
dep = $builddir/release/dep/src-main.c.o.d
|
dep = $builddir/release/dep/src-main.c.o.d
|
||||||
|
|
||||||
build $builddir/release/pss-total: link_release $builddir/release/obj/src-main.c.o | || $builddir/release/obj $builddir/release/dep
|
build $builddir/release/pss-total-waybar: link_release $builddir/release/obj/src-main.c.o | || $builddir/release/obj $builddir/release/dep
|
||||||
build release: phony $builddir/release/pss-total
|
build release: phony $builddir/release/pss-total-waybar
|
||||||
# END TARGET release
|
# END TARGET release
|
||||||
|
|
||||||
# BEGIN TARGET main
|
# BEGIN TARGET main
|
||||||
|
@ -80,6 +60,26 @@ build $builddir/main/dep: mkdir
|
||||||
build $builddir/main/obj/src-main.c.o: cc_main src/main.c
|
build $builddir/main/obj/src-main.c.o: cc_main src/main.c
|
||||||
dep = $builddir/main/dep/src-main.c.o.d
|
dep = $builddir/main/dep/src-main.c.o.d
|
||||||
|
|
||||||
build $builddir/main/pss-total: link_main $builddir/main/obj/src-main.c.o | || $builddir/main/obj $builddir/main/dep
|
build $builddir/main/pss-total-waybar: link_main $builddir/main/obj/src-main.c.o | || $builddir/main/obj $builddir/main/dep
|
||||||
build main: phony $builddir/main/pss-total
|
build main: phony $builddir/main/pss-total-waybar
|
||||||
# END TARGET main
|
# END TARGET main
|
||||||
|
|
||||||
|
# BEGIN TARGET debug
|
||||||
|
rule cc_debug
|
||||||
|
deps = gcc
|
||||||
|
depfile = $dep
|
||||||
|
command = cc -I. -fsanitize=address -O0 -g -MD -MF $dep -o $out -c $in
|
||||||
|
description = Building $in -> $out
|
||||||
|
rule link_debug
|
||||||
|
command = cc -fsanitize=address -o $out $in
|
||||||
|
description = Linking $out
|
||||||
|
|
||||||
|
build $builddir/debug/obj: mkdir
|
||||||
|
build $builddir/debug/dep: mkdir
|
||||||
|
|
||||||
|
build $builddir/debug/obj/src-main.c.o: cc_debug src/main.c
|
||||||
|
dep = $builddir/debug/dep/src-main.c.o.d
|
||||||
|
|
||||||
|
build $builddir/debug/pss-total-waybar: link_debug $builddir/debug/obj/src-main.c.o | || $builddir/debug/obj $builddir/debug/dep
|
||||||
|
build debug: phony $builddir/debug/pss-total-waybar
|
||||||
|
# END TARGET debug
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
mkdir -p /usr/local/bin
|
mkdir -p /usr/local/bin
|
||||||
cp build/release/pss-total /usr/local/bin
|
cp build/release/pss-total-waybar /usr/local/bin
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
compile_commands = true
|
compile_commands = true
|
||||||
|
|
||||||
[targets.main]
|
[targets.main]
|
||||||
outfile = "pss-total"
|
outfile = "pss-total-waybar"
|
||||||
compiler_flags = ["-I."]
|
compiler_flags = ["-I."]
|
||||||
sources = [
|
sources = [
|
||||||
"src/main.c",
|
"src/main.c",
|
||||||
|
|
145
src/main.c
145
src/main.c
|
@ -2,9 +2,11 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "lib/include/ns_fget_line.h"
|
#include "lib/include/ns_fget_line.h"
|
||||||
#include "lib/include/ns_str.h"
|
#include "lib/include/ns_str.h"
|
||||||
|
@ -22,15 +24,7 @@ double read_file(const char *filename) {
|
||||||
fp = fopen(filename, "r");
|
fp = fopen(filename, "r");
|
||||||
|
|
||||||
if (fp == NULL) {
|
if (fp == NULL) {
|
||||||
switch (errno) {
|
|
||||||
case EACCES:
|
|
||||||
return 0;
|
return 0;
|
||||||
break;
|
|
||||||
default:
|
|
||||||
perror("cannot open file pointer");
|
|
||||||
assert(fp != NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -41,7 +35,7 @@ double read_file(const char *filename) {
|
||||||
|
|
||||||
if (status == EOF) {
|
if (status == EOF) {
|
||||||
if (errno != 0) {
|
if (errno != 0) {
|
||||||
perror("error reading file");
|
perror("error reading smaps file");
|
||||||
ns_str_destroy(&line);
|
ns_str_destroy(&line);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -67,7 +61,7 @@ double read_file(const char *filename) {
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
double get_total_KiB(void) {
|
||||||
DIR *proc_dp;
|
DIR *proc_dp;
|
||||||
struct dirent *proc_ent;
|
struct dirent *proc_ent;
|
||||||
Str smaps_path = {0};
|
Str smaps_path = {0};
|
||||||
|
@ -108,40 +102,133 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
closedir(proc_dp);
|
closedir(proc_dp);
|
||||||
|
|
||||||
if (argc == 2) {
|
return total_KiB;
|
||||||
if ((strcmp(argv[1], "--pretty") == 0) || (strcmp(argv[1], "-p") == 0)) {
|
}
|
||||||
const char *prefixes[] = {"KiB", "MiB", "GiB"};
|
|
||||||
size_t i = 0;
|
size_t get_memtotal(void) {
|
||||||
while (total_KiB >= 1024 && i < 2) {
|
FILE *meminfo_fp;
|
||||||
total_KiB /= 1024;
|
Str line = {0};
|
||||||
i++;
|
int status;
|
||||||
|
size_t memtotal;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
meminfo_fp = fopen("/proc/meminfo", "r");
|
||||||
|
|
||||||
|
if (meminfo_fp == NULL) {
|
||||||
|
perror("cannot open file pointer to /proc/meminfo");
|
||||||
|
assert(meminfo_fp != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%0.2f %s\n", total_KiB, prefixes[i]);
|
ns_str_init_empty(&line, 256);
|
||||||
exit(0);
|
|
||||||
} else if ((strcmp(argv[1], "--help") == 0) ||
|
errno = 0;
|
||||||
(strcmp(argv[1], "-h") == 0)) {
|
status = ns_fget_line(meminfo_fp, &line);
|
||||||
|
|
||||||
|
if (status == EOF) {
|
||||||
|
if (errno != 0) {
|
||||||
|
perror("error reading meminfo");
|
||||||
|
fclose(meminfo_fp);
|
||||||
|
ns_str_destroy(&line);
|
||||||
|
assert(errno == 0);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "/proc/meminfo is empty... something is wrong.\n");
|
||||||
|
fclose(meminfo_fp);
|
||||||
|
ns_str_destroy(&line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = sscanf(line.arr, "MemTotal: %lu", &memtotal);
|
||||||
|
|
||||||
|
if (status != 1) {
|
||||||
|
fprintf(stderr, "MemTotal is not on the first line of /proc/meminfo??? \n");
|
||||||
|
fclose(meminfo_fp);
|
||||||
|
ns_str_destroy(&line);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(meminfo_fp);
|
||||||
|
ns_str_destroy(&line);
|
||||||
|
|
||||||
|
return memtotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
void get_json(char *json, size_t json_len) {
|
||||||
|
const char *prefixes[] = {"KiB", "MiB", "GiB"};
|
||||||
|
const char *classes[] = {"low", "quarter", "half", "three_quarters",
|
||||||
|
"nine_tenths"};
|
||||||
|
char mem_text[16] = {0};
|
||||||
|
size_t prefix_index = 0, classes_index = 0;
|
||||||
|
double total_KiB = 0, pretty_total = 0, percentage_use = 0;
|
||||||
|
|
||||||
|
total_KiB = get_total_KiB();
|
||||||
|
pretty_total = total_KiB;
|
||||||
|
|
||||||
|
while (pretty_total >= 1024 && prefix_index < 2) {
|
||||||
|
pretty_total /= 1024;
|
||||||
|
prefix_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf((char *restrict)&mem_text, 16, "%0.2f %s", pretty_total,
|
||||||
|
prefixes[prefix_index]);
|
||||||
|
|
||||||
|
percentage_use = total_KiB / get_memtotal();
|
||||||
|
|
||||||
|
classes_index = 0;
|
||||||
|
if (percentage_use >= 0.9) {
|
||||||
|
classes_index = 4;
|
||||||
|
} else if (percentage_use >= 0.75) {
|
||||||
|
classes_index = 3;
|
||||||
|
} else if (percentage_use >= 0.50) {
|
||||||
|
classes_index = 2;
|
||||||
|
} else if (percentage_use >= 0.25) {
|
||||||
|
classes_index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(json, json_len,
|
||||||
|
"{\"text\":\"%s\",\"class\":\"%s\",\"percentage\":%0.2f}", mem_text,
|
||||||
|
classes[classes_index], percentage_use * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// signal stuff
|
||||||
|
static volatile sig_atomic_t run = 1;
|
||||||
|
static void stop(int _) { run = 0; }
|
||||||
|
|
||||||
|
#define JSON_LEN 64
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
char json[JSON_LEN] = {0};
|
||||||
|
|
||||||
|
if (argc == 2) {
|
||||||
|
if ((strcmp(argv[1], "--help") == 0) || (strcmp(argv[1], "-h") == 0)) {
|
||||||
printf("DESCRIPTION\n");
|
printf("DESCRIPTION\n");
|
||||||
printf(
|
printf(
|
||||||
" pss-total: sum proportional set size of every process for "
|
" pss-total-waybar: sum proportional set size of every process for "
|
||||||
"accurate memory\n");
|
"accurate memory\n");
|
||||||
printf(
|
printf(
|
||||||
" usage statistics. In non-pretty mode, the number is given in "
|
" usage statistics. This branch outputs json for use in waybar.\n");
|
||||||
"kibibytes.\n");
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("SUMMARY\n");
|
printf("SUMMARY\n");
|
||||||
printf(" pss-total [OPTIONS]\n");
|
printf(" pss-total-waybar [OPTIONS]\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("OPTIONS\n");
|
printf("OPTIONS\n");
|
||||||
printf(" -p, --pretty\n");
|
|
||||||
printf(" format output using sensible units: KiB, MiB, or GiB.\n");
|
|
||||||
printf("\n");
|
|
||||||
printf(" -h, --help\n");
|
printf(" -h, --help\n");
|
||||||
printf(" print this help message.\n");
|
printf(" print this help message.\n");
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%.0f\n", total_KiB);
|
signal(SIGINT, stop);
|
||||||
|
signal(SIGTERM, stop);
|
||||||
|
|
||||||
|
while (run) {
|
||||||
|
memset(json, 0, JSON_LEN);
|
||||||
|
get_json((char *)&json, JSON_LEN);
|
||||||
|
printf("%s\n", json);
|
||||||
|
fflush(stdout);
|
||||||
|
if (run) {
|
||||||
|
sleep(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
rm /usr/local/bin/pss-total
|
rm /usr/local/bin/pss-total-waybar
|
||||||
|
|
Loading…
Reference in a new issue