Changeset 77
- Timestamp:
- 06/01/05 05:32:25 (4 years ago)
- Files:
-
- TODO (modified) (2 diffs)
- debian/changelog (modified) (1 diff)
- src/memory.c (modified) (6 diffs)
- src/memory.h (modified) (1 diff)
- src/opts.c (modified) (3 diffs)
- src/swaps.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
TODO
r76 r77 1 Error Reporting 2 - Unify logging/printing code: print-only or dynamic choice1 Output 2 - Print version number with help output; add --version option 3 3 - Ensure minimal repetition of error/warning messages 4 5 6 Policy Weaknesses7 8 Current policy is a bit weak when it comes to filesystem caching. The problem9 is that cache populations grow and grow until they hit the limit of available10 physical memory--creating an arguably false impression of memory shortage. The11 flexibility of the Linux virtual memory subsystem makes this, as far as I can12 see at this stage, impossible to diagnose directly.13 14 Most noticeable symptom: existing swapfiles are freed up sometime between system15 boot (when little data is cached and most physical memory is still free) and the16 moment when ever-growing caches push the percentage of free memory below our17 daemon's allocation threshold. We end up allocating a new swapfile shortly18 after deallocating our last one, just as the user is getting into the swing of19 things and expects his system to respond smoothly. While we're setting up that20 new swapfile, it doesn't. This is hard to anticipate; starting up in bull mode21 may help as a practical matter by deferring the decision to deallocate, but22 only if the associated cooldown period is long enough for filesystem caches to23 fill up again and bring the system into a "steady state."24 25 There are other cases that can trigger this behaviour, though. Consider this26 situation: some application X eats up huge amounts of virtual memory, most of27 which is in active use and therefore resides in physical memory. Swap is full28 of rarely-used virtual memory pages. Little or no filesystem caching occurs.29 Next, X finishes and suddenly we have lots of free physical memory--although30 swap remains densely populated. I'll need to do some math (probably quite31 simple, once I have the right formula) to figure out what can and cannot happen32 here.33 34 Scenario A: if most of the swapped-out data is touched again before we go into35 bear mode and consider deallocating, we're fine. We'll end up freeing largely36 unused swap space.37 38 Scenario B: if swap is deallocated at this stage, any remaining data it held39 will have to be read back in a hurry--plus, continued system operation may be40 suboptimal because some of that data is "colder" than filesystem data that could41 have been cached in the physical memory that X left free in its wake.42 43 Scenario C: if the "data vacuum" left by X is filled up by filesystem caches, we44 may end up thinking (once again) that we're short on memory--and allocating swap45 space that we won't be needing at all. Bull mode will be prolonged when a46 return to bear mode is in order.47 48 One consolation: since filesystem caches are never swapped to disk, they cannot49 exceed physical memory size. This means that the algorithm, for any acceptable50 set of parameters, can "overshoot" by at most a single swapfile.51 52 We could try to distinguish "false shortages" from real memory needs by53 ensuring that there is some "tripwire swap"--perhaps an existing conventional54 swap partition, or a special swapfile numbered zero. An increase in the55 population of this swap would indicate true memory shortage. The only problem56 is that the system may not resort to using the tripwire swap until it is already57 desperate! Can we set a positive priority to make the tripwire slightly more58 sensitive? We'd also have to clean this file up from time to time, because once59 it fills up the mechanism breaks down.60 4 61 5 … … 66 10 inbetween. Maybe this isn't the best way to do it. 67 11 68 What if we inhibited deallocations not just in bull mode, but instead required 69 that the percentage of available space was above the deallocation limit for an 70 entire cooldown period? 12 What if we inhibited deallocations until the percentage of available space 13 remained above the deallocation limit for an entire cooldown period? 71 14 debian/changelog
r76 r77 1 1 swapspace (1.3) unstable; urgency=low 2 2 3 * Consider part of non-dirty cached memory to be free space 3 * Consider part of non-dirty cached memory (and buffers) to be free space 4 * Re-tuned default parameters for new accounting 4 5 * Unified logging code--it's not pretty, but it's prettier 5 6 * No longer bother with "negotiable" minimum swapfile sizes 6 7 * Clarified startup message ("require n extra bytes" to "would prefer []") 7 * Documented existing policy weaknesses, possible solutions8 8 * Systematic rounding of swap sizes to page size 9 * Pad help output to align long options names vertically 10 * Fix: "smaller than expected" informational message was printed too often 9 11 10 12 -- Jeroen T. Vermeulen <jtv@sipa.or.th> Thu, 26 May 2005 17:00:00 +0700 src/memory.c
r76 r77 31 31 32 32 33 /// Lower bound to percentage of memory/swap space left unused34 static int lower_freelimit= 5;35 /// Upper bound to percentage of memory/swap space left unused36 static int upper_freelimit= 80;37 38 /// Configuration item: target for percentage of free space after adding swap33 /// Lower bound to percentage of memory/swap space kept available 34 static int lower_freelimit=10; 35 /// Upper bound to percentage of memory/swap space kept available 36 static int upper_freelimit=60; 37 38 /// Configuration item: target percentage of available space after adding swap 39 39 static int freetarget=25; 40 40 41 /// Configuration item: what percentage of buffer space do we consider "free"? 42 static int buffer_meekness=20; 43 41 44 // TODO: Make this adaptive based on actual cache usage, to avoid thrashing? 45 // TODO: Any way of detecting actual cache flexibility or minimum size? 42 46 /// Configuration item: what percentage of cache space do we consider "free"? 43 static int cache_meekness= 50;47 static int cache_meekness=80; 44 48 45 49 char *set_freetarget(long long pct) … … 58 62 { 59 63 upper_freelimit = (int)pct; 64 return NULL; 65 } 66 67 char *set_buffer_meekness(long long pct) 68 { 69 buffer_meekness = (int)pct; 60 70 return NULL; 61 71 } … … 158 168 memsize_t MemTotal, 159 169 MemFree, 170 Buffers, 160 171 Cached, 161 172 Dirty, … … 171 182 switch (inf->entry[0]) 172 183 { 184 case 'B': 185 if (strcmp(inf->entry, "Buffers:")==0) st->Buffers = inf->value; 186 break; 173 187 case 'C': 174 188 if (strcmp(inf->entry, "Cached:")==0) st->Cached = inf->value; … … 227 241 } 228 242 return init_req != MEMSIZE_ERROR; 243 } 244 245 246 /// How much buffer space can we expect the system to free up? 247 static inline memsize_t buffers_free(const struct memstate *st) 248 { 249 return (st->Buffers/100) * buffer_meekness; 229 250 } 230 251 … … 265 286 * considered in-use. 266 287 */ 267 return st->MemFree + st->SwapFree + st->SwapCached + cache_free(st); 288 return st->MemFree + 289 st->SwapFree + 290 st->SwapCached + 291 buffers_free(st) + 292 cache_free(st); 268 293 } 269 294 src/memory.h
r76 r77 40 40 char *set_upper_freelimit(long long pct); 41 41 char *set_freetarget(long long pct); 42 char *set_buffer_meekness(long long pct); 42 43 char *set_cache_meekness(long long pct); 43 44 src/opts.c
r76 r77 61 61 static const struct option options[] = 62 62 { 63 { "cache_meekness", 'w', at_num, 0, 100, set_cache_meekness, 64 "Consider n% of cache memory to be free space" }, 63 { "buffer_meekness", 'B', at_num, 0, 100, set_buffer_meekness, 64 "Consider n% of buffer memory to be \"available\"" }, 65 { "cache_meekness", 'C', at_num, 0, 100, set_cache_meekness, 66 "Consider n% of cache memory to be \"available\"" }, 65 67 { "configfile", 'c', at_str, 1, PATH_MAX, set_configfile, 66 68 "Use configuration file s" }, … … 70 72 "Run quietly in background" }, 71 73 { "freetarget", 'f', at_num, 2, 99, set_freetarget, 72 "Aim for n% of free space" },74 "Aim for n% of available space" }, 73 75 { "help", 'h', at_none, 0, 0, set_help, 74 76 "Display usage information" }, 75 77 { "lower_freelimit", 'l', at_num, 0, 99, set_lower_freelimit, 76 "Try to keep at least n% of memory/swap space free" },78 "Try to keep at least n% of memory/swap available" }, 77 79 { "max_swapsize", 'M', at_num, PAGE_SIZE, LLONG_MAX, set_max_swapsize, 78 80 "Restrict swapfiles to n bytes" }, … … 163 165 for (int i=0; i < sizeof(options)/sizeof(*options); ++i) 164 166 { 167 static const char pad[] = " "; 165 168 const char *const pt = argproto(i, true); 166 printf(" -%c%s, --%s%s%*s\t%s\n", 169 size_t ptlen; 170 171 ptlen = strlen(pt); 172 assert(ptlen < strlen(pad)); 173 174 printf(" -%c%s,%s--%s%s%*s\t%s\n", 167 175 options[i].shortopt, 168 176 pt, 177 pad+ptlen, 169 178 options[i].name, 170 179 argproto(i, false), src/swaps.c
r76 r77 504 504 expected, 505 505 found); 506 else if (!quiet && unlikely(found < (expected + PAGE_SIZE)))506 else if (!quiet && unlikely(found+2*PAGE_SIZE < expected)) 507 507 log_discrep(LOG_INFO, 508 508 "smaller than expected", … … 566 566 char namebuf[30]; 567 567 snprintf(namebuf, sizeof(namebuf), "%d", file); 568 if (!quiet) log_ str(LOG_NOTICE, "Retiring swapfile", namebuf);568 if (!quiet) log_int(LOG_NOTICE, "Retiring swapfile", file); 569 569 if (unlikely(swapoff(namebuf) == -1)) return false; 570 570 swapfiles[file].size = 0;
