summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authordormando <dormando@rydia.net>2017-12-18 15:05:01 -0800
committerdormando <dormando@rydia.net>2017-12-18 15:05:01 -0800
commitaa552fed9d9cffd10197bb3b2a62ad82ece62d5b (patch)
tree3dd0f908d66d1740653faf456a9e60f381c37310 /scripts
parent95565abedf95b8542582cdab6f2d6c8b1e5eb278 (diff)
downloadmemcached-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-xscripts/memcached-automove-extstore31
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.