|
29 | 29 | */ |
30 | 30 |
|
31 | 31 | #include <limits.h> |
| 32 | +#include <math.h> |
32 | 33 | #include <stdio.h> |
33 | 34 | #include <stdlib.h> |
34 | 35 | #include <stdint.h> |
@@ -149,8 +150,61 @@ static void *zrealloc_pmem(void *ptr, size_t size) { |
149 | 150 | static size_t pmem_threshold = UINT_MAX; |
150 | 151 | static size_t used_memory = 0; |
151 | 152 | static size_t used_pmem_memory = 0; |
| 153 | +static double pmem_dram_ratio = 0.0; |
| 154 | +static int use_ratio = 0; |
| 155 | +static unsigned int dynamic_min_threshold = 0; |
| 156 | +static unsigned int dynamic_max_threshold = 0; |
| 157 | +static int zmalloc_counter = 0; |
| 158 | + |
152 | 159 | pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER; |
153 | 160 |
|
| 161 | +#define THRESHOLD_STEP_NORMAL 0.05 |
| 162 | +#define THRESHOLD_STEP_AGGRESIVE (THRESHOLD_STEP_NORMAL*5) |
| 163 | +#define THRESHOLD_UP(val, step) ((size_t)ceil((1+(step))*val)) |
| 164 | +#define THRESHOLD_DOWN(val, step) ((size_t)floor((1-(step))*val)) |
| 165 | + |
| 166 | +static inline size_t absDiff(size_t a, size_t b) { |
| 167 | + return a > b ? (a - b) : (b - a); |
| 168 | +} |
| 169 | + |
| 170 | +static void adjustPmemThresholdCycle(void) { |
| 171 | + if (use_ratio) { |
| 172 | + if (zmalloc_counter++ == 1000) { |
| 173 | + zmalloc_counter = 0; |
| 174 | + /* Difference between target ratio and current ratio in last checkpoint*/ |
| 175 | + static double ratio_diff_checkpoint; |
| 176 | + /* PMEM and DRAM utilization in last checkpoint*/ |
| 177 | + static size_t total_memory_checkpoint; |
| 178 | + size_t pmem_memory = zmalloc_used_pmem_memory(); |
| 179 | + size_t dram_memory = zmalloc_used_memory(); |
| 180 | + size_t total_memory_current = pmem_memory + dram_memory; |
| 181 | + // do not modify threshold when change in memory usage is too small |
| 182 | + if (absDiff(total_memory_checkpoint, total_memory_current) > 100) { |
| 183 | + double current_ratio = (double)pmem_memory/dram_memory; |
| 184 | + double current_ratio_diff = fabs(current_ratio - pmem_dram_ratio); |
| 185 | + if (current_ratio_diff > 0.02) { |
| 186 | + //current ratio is worse than moment before |
| 187 | + double variableMultipler = current_ratio/pmem_dram_ratio; |
| 188 | + double step = (current_ratio_diff < ratio_diff_checkpoint) ? |
| 189 | + variableMultipler*THRESHOLD_STEP_NORMAL : variableMultipler*THRESHOLD_STEP_AGGRESIVE; |
| 190 | + size_t threshold = zmalloc_get_threshold(); |
| 191 | + if (pmem_dram_ratio < current_ratio) { |
| 192 | + size_t higher_threshold = THRESHOLD_UP(threshold,step); |
| 193 | + if (higher_threshold <= dynamic_max_threshold) |
| 194 | + zmalloc_set_threshold(higher_threshold); |
| 195 | + } else { |
| 196 | + size_t lower_threshold = THRESHOLD_DOWN(threshold,step); |
| 197 | + if (lower_threshold >= dynamic_min_threshold) |
| 198 | + zmalloc_set_threshold(lower_threshold); |
| 199 | + } |
| 200 | + } |
| 201 | + ratio_diff_checkpoint = current_ratio_diff; |
| 202 | + } |
| 203 | + total_memory_checkpoint = total_memory_current; |
| 204 | + } |
| 205 | + } |
| 206 | +} |
| 207 | + |
154 | 208 | static void zmalloc_default_oom(size_t size) { |
155 | 209 | fprintf(stderr, "zmalloc: Out of memory trying to allocate %zu bytes\n", |
156 | 210 | size); |
@@ -263,6 +317,7 @@ static void *zrealloc_pmem(void *ptr, size_t size) { |
263 | 317 | #endif |
264 | 318 |
|
265 | 319 | void *zmalloc(size_t size) { |
| 320 | + adjustPmemThresholdCycle(); |
266 | 321 | return (size < pmem_threshold) ? zmalloc_dram(size) : zmalloc_pmem(size); |
267 | 322 | } |
268 | 323 |
|
@@ -299,6 +354,7 @@ void *zcalloc_dram(size_t size) { |
299 | 354 | } |
300 | 355 |
|
301 | 356 | void *zcalloc(size_t size) { |
| 357 | + adjustPmemThresholdCycle(); |
302 | 358 | return (size < pmem_threshold) ? zcalloc_dram(size) : zcalloc_pmem(size); |
303 | 359 | } |
304 | 360 |
|
@@ -418,6 +474,15 @@ void zmalloc_set_threshold(size_t threshold) { |
418 | 474 | pmem_threshold = threshold; |
419 | 475 | } |
420 | 476 |
|
| 477 | +void zmalloc_set_ratio(double ratio) { |
| 478 | + use_ratio = 1; |
| 479 | + pmem_dram_ratio = ratio; |
| 480 | +} |
| 481 | +void zmalloc_set_threshold_range(unsigned int min, unsigned int max) { |
| 482 | + dynamic_min_threshold = min; |
| 483 | + dynamic_max_threshold = max; |
| 484 | +} |
| 485 | + |
421 | 486 | /* Get the RSS information in an OS-specific way. |
422 | 487 | * |
423 | 488 | * WARNING: the function zmalloc_get_rss() is not designed to be fast |
|
0 commit comments