util: introduce physical_memory_scale() to unify how we scale by physical memory
The various bits of code did the scaling all different, let's unify this, given that the code is not trivial.
This commit is contained in:
parent
799ec13412
commit
d8cf2ac79b
|
@ -805,6 +805,33 @@ uint64_t physical_memory(void) {
|
|||
return MIN(mem, lim);
|
||||
}
|
||||
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max) {
|
||||
uint64_t p, m, ps, r;
|
||||
|
||||
assert(max > 0);
|
||||
|
||||
/* Returns the physical memory size, multiplied by v divided by max. Returns UINT64_MAX on overflow. On success
|
||||
* the result is a multiple of the page size (rounds down). */
|
||||
|
||||
ps = page_size();
|
||||
assert(ps > 0);
|
||||
|
||||
p = physical_memory() / ps;
|
||||
assert(p > 0);
|
||||
|
||||
m = p * v;
|
||||
if (m / p != v)
|
||||
return UINT64_MAX;
|
||||
|
||||
m /= max;
|
||||
|
||||
r = m * ps;
|
||||
if (r / ps != m)
|
||||
return UINT64_MAX;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param) {
|
||||
int r;
|
||||
|
||||
|
|
|
@ -184,6 +184,7 @@ int namespace_open(pid_t pid, int *pidns_fd, int *mntns_fd, int *netns_fd, int *
|
|||
int namespace_enter(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd);
|
||||
|
||||
uint64_t physical_memory(void);
|
||||
uint64_t physical_memory_scale(uint64_t v, uint64_t max);
|
||||
|
||||
int update_reboot_parameter_and_warn(const char *param);
|
||||
|
||||
|
|
|
@ -2821,7 +2821,7 @@ int config_parse_memory_limit(
|
|||
return 0;
|
||||
}
|
||||
} else
|
||||
bytes = (((physical_memory() / page_size()) * (uint64_t) r) / 100) * page_size();
|
||||
bytes = physical_memory_scale(r, 100U);
|
||||
|
||||
if (bytes < 1) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Memory limit '%s' too small. Ignoring.", rvalue);
|
||||
|
|
|
@ -853,7 +853,7 @@ int config_parse_tmpfs_size(
|
|||
/* First, try to parse as percentage */
|
||||
r = parse_percent(rvalue);
|
||||
if (r > 0 && r < 100)
|
||||
*sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) r) / 100U));
|
||||
*sz = physical_memory_scale(r, 100U);
|
||||
else {
|
||||
uint64_t k;
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ static void manager_reset_config(Manager *m) {
|
|||
m->idle_action_usec = 30 * USEC_PER_MINUTE;
|
||||
m->idle_action = HANDLE_IGNORE;
|
||||
|
||||
m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */
|
||||
m->runtime_dir_size = physical_memory_scale(10U, 100U); /* 10% */
|
||||
m->user_tasks_max = 12288;
|
||||
m->sessions_max = 8192;
|
||||
m->inhibitors_max = 8192;
|
||||
|
|
|
@ -273,7 +273,42 @@ static void test_physical_memory(void) {
|
|||
assert_se(p < UINT64_MAX);
|
||||
assert_se(p % page_size() == 0);
|
||||
|
||||
log_info("Memory: %s", format_bytes(buf, sizeof(buf), p));
|
||||
log_info("Memory: %s (%" PRIu64 ")", format_bytes(buf, sizeof(buf), p), p);
|
||||
}
|
||||
|
||||
static void test_physical_memory_scale(void) {
|
||||
uint64_t p;
|
||||
|
||||
p = physical_memory();
|
||||
|
||||
assert_se(physical_memory_scale(0, 100) == 0);
|
||||
assert_se(physical_memory_scale(100, 100) == p);
|
||||
|
||||
log_info("Memory original: %" PRIu64, physical_memory());
|
||||
log_info("Memory scaled by 50%%: %" PRIu64, physical_memory_scale(50, 100));
|
||||
log_info("Memory divided by 2: %" PRIu64, physical_memory() / 2);
|
||||
log_info("Page size: %zu", page_size());
|
||||
|
||||
/* There might be an uneven number of pages, hence permit these calculations to be half a page off... */
|
||||
assert_se(page_size()/2 + physical_memory_scale(50, 100) - p/2 <= page_size());
|
||||
assert_se(physical_memory_scale(200, 100) == p*2);
|
||||
|
||||
assert_se(physical_memory_scale(0, 1) == 0);
|
||||
assert_se(physical_memory_scale(1, 1) == p);
|
||||
assert_se(physical_memory_scale(2, 1) == p*2);
|
||||
|
||||
assert_se(physical_memory_scale(0, 2) == 0);
|
||||
|
||||
assert_se(page_size()/2 + physical_memory_scale(1, 2) - p/2 <= page_size());
|
||||
assert_se(physical_memory_scale(2, 2) == p);
|
||||
assert_se(physical_memory_scale(4, 2) == p*2);
|
||||
|
||||
assert_se(physical_memory_scale(0, UINT32_MAX) == 0);
|
||||
assert_se(physical_memory_scale(UINT32_MAX, UINT32_MAX) == p);
|
||||
|
||||
/* overflow */
|
||||
assert_se(physical_memory_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
@ -291,6 +326,7 @@ int main(int argc, char *argv[]) {
|
|||
test_execute_directory();
|
||||
test_raw_clone();
|
||||
test_physical_memory();
|
||||
test_physical_memory_scale();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue