Skip to content

Commit

Permalink
Introduce UserMemTotal and calculate MemAvailablePercent based on it
Browse files Browse the repository at this point in the history
Shmem/tmpfs may block a large part of RAM. This memory cannot be freed
by killing processes. Before this change, we could get into a
situation where earlyoom kills *every* process, but still cannot
achieve the desired MemAvailablePercent.

Fixes: #274
Fixes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1012870
  • Loading branch information
rfjakob committed Feb 5, 2023
1 parent 81c0d70 commit 459d762
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 14 deletions.
6 changes: 3 additions & 3 deletions main.c
Expand Up @@ -341,8 +341,8 @@ int main(int argc, char* argv[])
}

// Print memory limits
fprintf(stderr, "mem total: %4lld MiB, swap total: %4lld MiB\n",
m.MemTotalKiB / 1024, m.SwapTotalKiB / 1024);
fprintf(stderr, "user mem total: %4lld MiB, swap total: %4lld MiB\n",
m.UserMemTotalKiB / 1024, m.SwapTotalKiB / 1024);
fprintf(stderr, "sending SIGTERM when mem <= " PRIPCT " and swap <= " PRIPCT ",\n",
args.mem_term_percent, args.swap_term_percent);
fprintf(stderr, " SIGKILL when mem <= " PRIPCT " and swap <= " PRIPCT "\n",
Expand Down Expand Up @@ -404,7 +404,7 @@ static unsigned sleep_time_ms(const poll_loop_args_t* args, const meminfo_t* m)
const unsigned min_sleep = 100;
const unsigned max_sleep = 1000;

long long mem_headroom_kib = (long long)((m->MemAvailablePercent - args->mem_term_percent) * (double)m->MemTotalKiB / 100);
long long mem_headroom_kib = (long long)((m->MemAvailablePercent - args->mem_term_percent) * (double)m->UserMemTotalKiB / 100);
if (mem_headroom_kib < 0) {
mem_headroom_kib = 0;
}
Expand Down
18 changes: 9 additions & 9 deletions meminfo.c
Expand Up @@ -95,7 +95,7 @@ meminfo_t parse_meminfo()
m.MemTotalKiB = get_entry_fatal("MemTotal:", buf);
m.SwapTotalKiB = get_entry_fatal("SwapTotal:", buf);
m.AnonPagesKiB = get_entry_fatal("AnonPages:", buf);
long long SwapFree = get_entry_fatal("SwapFree:", buf);
m.SwapFreeKiB = get_entry_fatal("SwapFree:", buf);

m.MemAvailableKiB = get_entry("MemAvailable:", buf);
if (m.MemAvailableKiB < 0) {
Expand All @@ -107,11 +107,13 @@ meminfo_t parse_meminfo()
}
}

// Calculated values
m.UserMemTotalKiB = m.MemAvailableKiB + m.AnonPagesKiB;

// Calculate percentages
m.MemAvailablePercent = (double)m.MemAvailableKiB * 100 / (double)m.MemTotalKiB;
m.AnonPagesPercent = (double)m.AnonPagesKiB * 100 / (double)m.MemTotalKiB;
m.MemAvailablePercent = (double)m.MemAvailableKiB * 100 / (double)m.UserMemTotalKiB;
if (m.SwapTotalKiB > 0) {
m.SwapFreePercent = (double)SwapFree * 100 / (double)m.SwapTotalKiB;
m.SwapFreePercent = (double)m.SwapFreeKiB * 100 / (double)m.SwapTotalKiB;
} else {
m.SwapFreePercent = 0;
}
Expand Down Expand Up @@ -302,13 +304,11 @@ long long get_vm_rss_kib(int pid)
*/
void print_mem_stats(int __attribute__((format(printf, 1, 2))) (*out_func)(const char* fmt, ...), const meminfo_t m)
{
out_func("mem avail: %5lld of %5lld MiB (" PRIPCT "), swap free: %4lld of %4lld MiB (" PRIPCT "), anon: %5lld MiB (" PRIPCT ")\n",
out_func("mem avail: %5lld of %5lld MiB (" PRIPCT "), swap free: %4lld of %4lld MiB (" PRIPCT ")\n",
m.MemAvailableKiB / 1024,
m.MemTotalKiB / 1024,
m.UserMemTotalKiB / 1024,
m.MemAvailablePercent,
m.SwapFreeKiB / 1024,
m.SwapTotalKiB / 1024,
m.SwapFreePercent,
m.AnonPagesKiB / 1024,
m.AnonPagesPercent);
m.SwapFreePercent);
}
7 changes: 5 additions & 2 deletions meminfo.h
Expand Up @@ -7,16 +7,19 @@
#include <stdbool.h>

typedef struct {
// Values from /proc/meminfo, in KiB or converted to MiB.
// Values from /proc/meminfo, in KiB
long long MemTotalKiB;
long long MemAvailableKiB;
long long SwapTotalKiB;
long long SwapFreeKiB;
long long AnonPagesKiB;
// Calculated values
// UserMemTotalKiB = MemAvailableKiB + AnonPagesKiB.
// Represents the total amount of memory that may be used by user processes.
long long UserMemTotalKiB;
// Calculated percentages
double MemAvailablePercent; // percent of total memory that is available
double SwapFreePercent; // percent of total swap that is free
double AnonPagesPercent; // percent of total memory that is used by processes
} meminfo_t;

typedef struct procinfo {
Expand Down

0 comments on commit 459d762

Please sign in to comment.