summaryrefslogtreecommitdiff
path: root/utils/lru
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2014-03-21 09:52:00 +0100
committerantirez <antirez@gmail.com>2014-03-21 09:52:05 +0100
commit6972f18cbd1b71ebaf4a8f077ab79a59ccaccea2 (patch)
treeab0150e9dbedaa9064a28c883c3714c79c76692a /utils/lru
parent4d2e8fa189665e8e76040da9642ca89ef55fba10 (diff)
downloadredis-6972f18cbd1b71ebaf4a8f077ab79a59ccaccea2.tar.gz
Add test-lru.rb to utils.
This is a program useful to evaluate the Redis LRU algorithm behavior.
Diffstat (limited to 'utils/lru')
-rw-r--r--utils/lru/README13
-rw-r--r--utils/lru/test-lru.rb112
2 files changed, 125 insertions, 0 deletions
diff --git a/utils/lru/README b/utils/lru/README
new file mode 100644
index 000000000..288189e3e
--- /dev/null
+++ b/utils/lru/README
@@ -0,0 +1,13 @@
+The test-lru.rb program can be used in order to check the behavior of the
+Redis approximated LRU algorithm against the theoretical output of true
+LRU algorithm.
+
+In order to use the program you need to recompile Redis setting the define
+REDIS_LRU_CLOCK_RESOLUTION to 1, by editing redis.h.
+This allows to execute the program in a fast way since the 1 ms resolution
+is enough for all the objects to have a different enough time stamp during
+the test.
+
+The program is executed like this:
+
+ ruby test-lru.rb > /tmp/lru.html
diff --git a/utils/lru/test-lru.rb b/utils/lru/test-lru.rb
new file mode 100644
index 000000000..d4b0f88cf
--- /dev/null
+++ b/utils/lru/test-lru.rb
@@ -0,0 +1,112 @@
+require 'rubygems'
+require 'redis'
+
+r = Redis.new
+r.config("SET","maxmemory","2000000")
+r.config("SET","maxmemory-policy","allkeys-lru")
+r.config("SET","maxmemory-samples",5)
+r.config("RESETSTAT")
+r.flushall
+
+puts <<EOF
+<html>
+<body>
+<style>
+.box {
+ width:5px;
+ height:5px;
+ float:left;
+ margin: 1px;
+}
+
+.old {
+ border: 1px black solid;
+}
+
+.new {
+ border: 1px green solid;
+}
+
+.ex {
+ background-color: #666;
+}
+</style>
+<pre>
+EOF
+
+# Fill
+oldsize = r.dbsize
+id = 0
+while true
+ id += 1
+ r.set(id,"foo")
+ newsize = r.dbsize
+ break if newsize == oldsize
+ oldsize = newsize
+end
+
+inserted = r.dbsize
+first_set_max_id = id
+puts "#{r.dbsize} keys inserted"
+
+# Access keys sequencially
+
+puts "Access keys sequencially"
+(1..first_set_max_id).each{|id|
+ r.get(id)
+# sleep 0.001
+}
+
+# Insert more 50% keys. We expect that the new keys
+half = inserted/2
+puts "Insert enough keys to evict half the keys we inserted"
+add = 0
+while true
+ add += 1
+ id += 1
+ r.set(id,"foo")
+ break if r.info['evicted_keys'].to_i >= half
+end
+
+puts "#{add} additional keys added."
+puts "#{r.dbsize} keys in DB"
+
+# Check if evicted keys respect LRU
+# We consider errors from 1 to N progressively more serious as they violate
+# more the access pattern.
+
+errors = 0
+e = 1
+edecr = 1.0/(first_set_max_id/2)
+(1..(first_set_max_id/2)).each{|id|
+ e -= edecr if e > 0
+ e = 0 if e < 0
+ if r.exists(id)
+ errors += e
+ end
+}
+
+puts "#{errors} errors!"
+puts "</pre>"
+
+# Generate the graphical representation
+(1..id).each{|id|
+ # Mark first set and added items in a different way.
+ c = "box"
+ if id <= first_set_max_id
+ c << " old"
+ else
+ c << " new"
+ end
+
+ # Add class if exists
+ c << " ex" if r.exists(id)
+ puts "<div class=\"#{c}\"></div>"
+}
+
+# Close HTML page
+
+puts <<EOF
+</body>
+</html>
+EOF