diff options
author | dormando <dormando@rydia.net> | 2017-12-18 15:05:01 -0800 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2017-12-18 15:05:01 -0800 |
commit | aa552fed9d9cffd10197bb3b2a62ad82ece62d5b (patch) | |
tree | 3dd0f908d66d1740653faf456a9e60f381c37310 /scripts | |
parent | 95565abedf95b8542582cdab6f2d6c8b1e5eb278 (diff) | |
download | memcached-aa552fed9d9cffd10197bb3b2a62ad82ece62d5b.tar.gz |
extstore: more page mover algorithm fixes
wasn't checking for "dirty" flag on a class before deciding it was too free,
so it would assign/remove/assign/remove/assign/remove, and tend to
over-remove slightly. Over time the global page pool would simply grow.
Also adjusts timing so draining the global page pool works better. multiple
classes can be drained into at once by nature of zeroing out the free limits
one at a time.
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/memcached-automove-extstore | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/scripts/memcached-automove-extstore b/scripts/memcached-automove-extstore index 3419620..fa7a11c 100755 --- a/scripts/memcached-automove-extstore +++ b/scripts/memcached-automove-extstore @@ -74,6 +74,7 @@ def determine_move(history, stats, diffs, memfree): w = history['w'][-1] oldest = (-1, 0) youngest = (-1, sys.maxsize) + too_free = False # Most bytes free decision = (-1, -1) if int(stats['slab_global_page_pool']) < memfree[0] / 2: @@ -107,11 +108,17 @@ def determine_move(history, stats, diffs, memfree): age = window_check(history, sid, 'age') / len(history['w']) # if > 2.5 pages free, and not dirty, reassign to global page pool - if slab['free_chunks'] > slab['chunks_per_page'] * MIN_PAGES_FOR_RECLAIM: - if window_check(history, sid, 'dirty') == 0 and small_slab == True: + if slab['free_chunks'] > slab['chunks_per_page'] * MIN_PAGES_FOR_RECLAIM and too_free == False: + dirt = window_check(history, sid, 'dirty') + excess = window_check(history, sid, 'excess_free') + if small_slab == True and dirt == 0: # If we're a small slab, don't hang on to free memory forever. decision = (sid, 0) - break + too_free = True + elif small_slab == False and dirt == 0 \ + and excess >= len(history['w']): + decision = (sid, 0) + too_free = True # are we the oldest slab class? (and a valid target) if small_slab == False: @@ -122,18 +129,18 @@ def determine_move(history, stats, diffs, memfree): youngest = (sid, age) - if pool_high and youngest[0] != -1: + if w.get('slab_pool_high') and youngest[0] != -1: # if global pool is too high, feed youngest large class. # decision = (0, youngest[0]) # No current way to assign directly from global to a class. # minimize the free chunks limiter and re-check. decision = (youngest[0], -2) - elif pool_low and oldest[0] != -1: + elif too_free == False and pool_low and oldest[0] != -1: # if pool is too low, take from oldest large class. if args.verbose: print("oldest: [class: {}] [age: {}]".format(int(oldest[0]), oldest[1])) decision = (oldest[0], 0) - elif youngest[0] != -1 and oldest[0] != -1 and youngest[0] != oldest[0]: + elif too_free == False and youngest[0] != -1 and oldest[0] != -1 and youngest[0] != oldest[0]: # youngest is outside of the tolerance ratio, move a page around. if args.verbose: print("old: [class: {}] [age: {:.2f}]\nyoung: [class: {}] [age: {:.2f}]".format( @@ -288,16 +295,20 @@ while True: decision = (-1, -1) if int(stats['evictions']) > 0: decision = determine_move(history, stats, diffs, memfree) - if int(decision[0]) > 0 and decision[1] >= 0: + if int(decision[0]) > 0 and int(decision[1]) >= 0: print("moving page from, to:", decision) if args.automove: run_move(s, decision) elif int(decision[0]) > 0 and decision[1] == -2: - # we've been told to zero out the memory limit and - # sleep for a bit. - last_memfree_check = 0 + # we've been told to zero out the memory limit. + # let the memfree check run "soon". + # this (purposefully) can slowly remove limits on + # multiple classes if global pool stays too high. + last_memfree_check = time() - 58 s.write("extstore free_memchunks {} {}\r\n".format(decision[0], 0)) s.readline() + if args.verbose: + print("relaxing free:", decision[0]) # Minimize sleeping if we just moved a page to global pool. |