Changeset 77

Show
Ignore:
Timestamp:
06/01/05 05:32:25 (4 years ago)
Author:
jtv
Message:

Revamped free-space accounting system

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • TODO

    r76 r77  
    1 Error Reporting 
    2  - Unify logging/printing code: print-only or dynamic choice 
     1Output 
     2 - Print version number with help output; add --version option 
    33 - Ensure minimal repetition of error/warning messages 
    4  
    5  
    6 Policy Weaknesses 
    7  
    8 Current policy is a bit weak when it comes to filesystem caching.  The problem 
    9 is that cache populations grow and grow until they hit the limit of available 
    10 physical memory--creating an arguably false impression of memory shortage.  The 
    11 flexibility of the Linux virtual memory subsystem makes this, as far as I can 
    12 see at this stage, impossible to diagnose directly. 
    13  
    14 Most noticeable symptom: existing swapfiles are freed up sometime between system 
    15 boot (when little data is cached and most physical memory is still free) and the 
    16 moment when ever-growing caches push the percentage of free memory below our 
    17 daemon's allocation threshold.  We end up allocating a new swapfile shortly 
    18 after deallocating our last one, just as the user is getting into the swing of 
    19 things and expects his system to respond smoothly.  While we're setting up that 
    20 new swapfile, it doesn't.  This is hard to anticipate; starting up in bull mode 
    21 may help as a practical matter by deferring the decision to deallocate, but 
    22 only if the associated cooldown period is long enough for filesystem caches to 
    23 fill up again and bring the system into a "steady state." 
    24  
    25 There are other cases that can trigger this behaviour, though.  Consider this 
    26 situation: some application X eats up huge amounts of virtual memory, most of 
    27 which is in active use and therefore resides in physical memory.  Swap is full 
    28 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--although 
    30 swap remains densely populated.  I'll need to do some math (probably quite 
    31 simple, once I have the right formula) to figure out what can and cannot happen 
    32 here. 
    33  
    34 Scenario A: if most of the swapped-out data is touched again before we go into 
    35 bear mode and consider deallocating, we're fine.  We'll end up freeing largely 
    36 unused swap space. 
    37  
    38 Scenario B: if swap is deallocated at this stage, any remaining data it held 
    39 will have to be read back in a hurry--plus, continued system operation may be 
    40 suboptimal because some of that data is "colder" than filesystem data that could 
    41 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, we 
    44 may end up thinking (once again) that we're short on memory--and allocating swap 
    45 space that we won't be needing at all.  Bull mode will be prolonged when a 
    46 return to bear mode is in order. 
    47  
    48 One consolation: since filesystem caches are never swapped to disk, they cannot 
    49 exceed physical memory size.  This means that the algorithm, for any acceptable 
    50 set of parameters, can "overshoot" by at most a single swapfile. 
    51  
    52 We could try to distinguish "false shortages" from real memory needs by 
    53 ensuring that there is some "tripwire swap"--perhaps an existing conventional 
    54 swap partition, or a special swapfile numbered zero.  An increase in the 
    55 population of this swap would indicate true memory shortage.  The only problem 
    56 is that the system may not resort to using the tripwire swap until it is already 
    57 desperate!  Can we set a positive priority to make the tripwire slightly more 
    58 sensitive?  We'd also have to clean this file up from time to time, because once 
    59 it fills up the mechanism breaks down. 
    604 
    615 
     
    6610inbetween.  Maybe this isn't the best way to do it. 
    6711 
    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? 
     12What if we inhibited deallocations until the percentage of available space 
     13remained above the deallocation limit for an entire cooldown period? 
    7114 
  • debian/changelog

    r76 r77  
    11swapspace (1.3) unstable; urgency=low 
    22 
    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 
    45  * Unified logging code--it's not pretty, but it's prettier 
    56  * No longer bother with "negotiable" minimum swapfile sizes 
    67  * Clarified startup message ("require n extra bytes" to "would prefer []") 
    7   * Documented existing policy weaknesses, possible solutions 
    88  * 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 
    911 
    1012 -- Jeroen T. Vermeulen <jtv@sipa.or.th>  Thu, 26 May 2005 17:00:00 +0700 
  • src/memory.c

    r76 r77  
    3131 
    3232 
    33 /// Lower bound to percentage of memory/swap space left unused 
    34 static int lower_freelimit=5
    35 /// Upper bound to percentage of memory/swap space left unused 
    36 static int upper_freelimit=80; 
    37  
    38 /// Configuration item: target for percentage of free space after adding swap  
     33/// Lower bound to percentage of memory/swap space kept available 
     34static int lower_freelimit=10
     35/// Upper bound to percentage of memory/swap space kept available 
     36static int upper_freelimit=60; 
     37 
     38/// Configuration item: target percentage of available space after adding swap  
    3939static int freetarget=25; 
    4040 
     41/// Configuration item: what percentage of buffer space do we consider "free"? 
     42static int buffer_meekness=20; 
     43 
    4144// TODO: Make this adaptive based on actual cache usage, to avoid thrashing? 
     45// TODO: Any way of detecting actual cache flexibility or minimum size? 
    4246/// Configuration item: what percentage of cache space do we consider "free"? 
    43 static int cache_meekness=50; 
     47static int cache_meekness=80; 
    4448 
    4549char *set_freetarget(long long pct) 
     
    5862{ 
    5963  upper_freelimit = (int)pct; 
     64  return NULL; 
     65} 
     66 
     67char *set_buffer_meekness(long long pct) 
     68{ 
     69  buffer_meekness = (int)pct; 
    6070  return NULL; 
    6171} 
     
    158168  memsize_t MemTotal, 
    159169            MemFree, 
     170            Buffers, 
    160171            Cached, 
    161172            Dirty, 
     
    171182  switch (inf->entry[0]) 
    172183  { 
     184  case 'B': 
     185    if (strcmp(inf->entry, "Buffers:")==0)         st->Buffers = inf->value; 
     186    break; 
    173187  case 'C': 
    174188    if (strcmp(inf->entry, "Cached:")==0)          st->Cached = inf->value; 
     
    227241  } 
    228242  return init_req != MEMSIZE_ERROR; 
     243} 
     244 
     245 
     246/// How much buffer space can we expect the system to free up? 
     247static inline memsize_t buffers_free(const struct memstate *st) 
     248{ 
     249  return (st->Buffers/100) * buffer_meekness; 
    229250} 
    230251 
     
    265286   * considered in-use. 
    266287   */ 
    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); 
    268293} 
    269294 
  • src/memory.h

    r76 r77  
    4040char *set_upper_freelimit(long long pct); 
    4141char *set_freetarget(long long pct); 
     42char *set_buffer_meekness(long long pct); 
    4243char *set_cache_meekness(long long pct); 
    4344 
  • src/opts.c

    r76 r77  
    6161static const struct option options[] = 
    6262{ 
    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\"" }, 
    6567  { "configfile",       'c', at_str,  1, PATH_MAX, set_configfile, 
    6668  "Use configuration file s" }, 
     
    7072  "Run quietly in background" }, 
    7173  { "freetarget",       'f', at_num,  2, 99, set_freetarget, 
    72   "Aim for n% of free space" }, 
     74  "Aim for n% of available space" }, 
    7375  { "help",             'h', at_none, 0, 0, set_help, 
    7476  "Display usage information" }, 
    7577  { "lower_freelimit",  'l', at_num,  0, 99, set_lower_freelimit, 
    76   "Try to keep at least n% of memory/swapspace free" }, 
     78  "Try to keep at least n% of memory/swap available" }, 
    7779  { "max_swapsize",     'M', at_num, PAGE_SIZE, LLONG_MAX, set_max_swapsize, 
    7880  "Restrict swapfiles to n bytes" }, 
     
    163165  for (int i=0; i < sizeof(options)/sizeof(*options); ++i) 
    164166  { 
     167    static const char pad[] = "   "; 
    165168    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", 
    167175        options[i].shortopt, 
    168176        pt, 
     177        pad+ptlen, 
    169178        options[i].name, 
    170179        argproto(i, false), 
  • src/swaps.c

    r76 r77  
    504504              expected, 
    505505              found); 
    506         else if (!quiet && unlikely(found < (expected + PAGE_SIZE))) 
     506        else if (!quiet && unlikely(found+2*PAGE_SIZE < expected)) 
    507507          log_discrep(LOG_INFO, 
    508508              "smaller than expected", 
     
    566566  char namebuf[30]; 
    567567  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); 
    569569  if (unlikely(swapoff(namebuf) == -1)) return false; 
    570570  swapfiles[file].size = 0;