Class: LambdaStoreHLL::Counter
- Inherits:
-
Object
- Object
- LambdaStoreHLL::Counter
- Defined in:
- lib/lambda-store-hll/counter.rb
Constant Summary collapse
- ADD_SCRIPT =
' local index = tonumber(KEYS[2]) local counter = redis.call("GETRANGE", KEYS[1], index, index) local str_len = tonumber(ARGV[2]) if(counter == "") then local str = "" for i=0,str_len-1 do str = str .. (i == index and ARGV[1] or string.char(0)) end redis.call("SET", KEYS[1], str) return 1 elseif string.byte(ARGV[1]) > string.byte(counter) then redis.call("SETRANGE", KEYS[1], index, ARGV[1]) return 1 end return 0 '
- ADD_SCRIPT_MIN =
'local a=tonumber(KEYS[2])local b=redis.call("GETRANGE",KEYS[1],a,a)local c=tonumber(ARGV[2])if b==""then local d=""for e=0,c-1 do d=d..(e==a and ARGV[1]or string.char(0))end;redis.call("SET",KEYS[1],d)return 1 elseif string.byte(ARGV[1])>string.byte(b)then redis.call("SETRANGE",KEYS[1],a,ARGV[1])return 1 end;return 0'
- COUNT_SCRIPT =
' local m = tonumber(ARGV[1]) local alpha = tonumber(ARGV[2]) local value = 0 local length = 0 local str = redis.call("GET", KEYS[1]) if not str then return 0 end for i=1,m do local max = string.byte(str:sub(i,i)) if max > 0 then length = length + 1 end value = value + 0.5 ^ max end local estimate = m ^ 2 * alpha / value --linear count if estimate < 2.5 * m and (length < m) then return (m * math.log(m/(m - length))) end return math.floor(estimate + 0.5) '
- COUNT_SCRIPT_MIN =
'local a=tonumber(ARGV[1])local b=tonumber(ARGV[2])local c=0;local d=0;local e=redis.call("GET",KEYS[1])if not e then return 0 end;for f=1,a do local g=string.byte(e:sub(f,f))if g>0 then d=d+1 end;c=c+0.5^g end;local h=a^2*b/c;if h<2.5*a and d<a then return a*math.log(a/(a-d))end;return math.floor(h+0.5)'
Instance Method Summary collapse
-
#add(k, v) ⇒ Object
do the hashing on this end to save excessive amounts of script being sent.
- #count(k) ⇒ Object
- #del(k) ⇒ Object
-
#initialize(redis, b: 10) ⇒ Counter
constructor
A new instance of Counter.
Constructor Details
#initialize(redis, b: 10) ⇒ Counter
Returns a new instance of Counter.
6 7 8 9 10 11 12 13 |
# File 'lib/lambda-store-hll/counter.rb', line 6 def initialize(redis, b: 10) raise "Accuracy not supported. Please choose a value of b between 4 and 16" if b < 4 || b > 16 @b = b @m = 2 ** b @redis = redis @hash_len = 32 - b @alpha = 0.7213/(1 + 1.079/@m) end |
Instance Method Details
#add(k, v) ⇒ Object
do the hashing on this end to save excessive amounts of script being sent
68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/lambda-store-hll/counter.rb', line 68 def add(k, v) #hash the string hash = Mmh3.hash32(v) #remove negatives but keep info hash = ((hash.abs << 1) | (hash.negative? ? 1 : 0)) #get the 10 bit bucket id int_bucket = (hash & (@m - 1)) @redis.eval(ADD_SCRIPT_MIN, :keys => [k, int_bucket], :argv => [rho(hash / @m).chr, @m]) end |
#count(k) ⇒ Object
80 81 82 |
# File 'lib/lambda-store-hll/counter.rb', line 80 def count(k) @redis.eval(COUNT_SCRIPT_MIN, :keys => [k], :argv => [@m, @alpha]) end |
#del(k) ⇒ Object
84 85 86 |
# File 'lib/lambda-store-hll/counter.rb', line 84 def del(k) @redis.del(k) end |