Implementation of a Redis zset data structure using Python

Source: Internet
Author: User
Tags benchmark

Redis has been used for more than 2 years, often lamented the graceful and lean redis, perfectly formed.

Recently preface out the idea of using Python to implement a zset data structure in memory.

The idea is this:

Hash + SortedList

Where hash is used to make the acquisition of the complexity of the key value into O (1)

and using Bisect module dichotomy method to implement other operations in SortedList O (logn)


The code below.

#coding =utf-8from bisect Import bisect_left,bisect_right,insort# Define node class Snode:def __init__ (Self,key=none, score= Float ('-inf '), next=none): Self.key = key Self.score = Score def __lt__ (Self,other): return self. Score < GetAttr (other, ' score ', other) def __gt__ (self,other): #没定义__gt__的话会导致bisect_right出问题, even if __lt__ Retu is already defined RN Self.score > GetAttr (Other, ' score ', other) #定义数组, with bisect Maintenance Order class Slist (object): Def __init__ (self): self.ke Y2node = {} Self.card = 0 self.orderlist = [] def findpos (self, snode): CurPos = Bisect_left (self. Orderlist,snode) while 1:if self.orderlist[curpos].key==snode.key:break curp OS + = 1 return curpos def insert (Self,key,score): If not isinstance (score,int): Raise Exception (' score mus t be integer ') Snode = Self.key2node.get (key) if snode:if score = = Snode.score:r Eturn 0 del Self.Orderlist[self.findpos (snode)] Snode.score = score Else:self.card + = 1 Snode = SN  Ode (key=key,score=score) Self.key2node[key] = Snode insort (self.orderlist, Snode) return 1 def        Delete (Self,key): Snode = Self.key2node.get (key) if not Snode:return 0 self.card-= 1 Del Self.orderlist[self.findpos (Snode)] del Self.key2node[key] del snode return 1 def search ( Self,key): Return Self.key2node.get (Key) class Sortedset:def __init__ (self): Self.slist = Slist () def Zadd (self, Key, score): Return Self.slist.insert (Key, score) def zrem (self, key): Return Self.slist.delet E (key) def zrank (self, key): #score相同则按字典序 Snode = Self.slist.key2node.get (key) if not snode:r Eturn None return Self.slist.findpos (Snode) def zrevrank (self, key): Return Self.zcard-1-Self.zrank (k EY) def zscore (self,Key): Snode = Self.slist.key2node.get (key) return GetAttr (Snode, ' score ', None) def zcount (self, start, end ): ol = self.slist.orderlist return Bisect_left (ol,end+1)-Bisect_right (ol,start-1) @property def ZCA RD (Self): return Self.slist.card def zrange (self, start, end, Withscores=false): #score相同则按字典序 nodes = sel F.SLIST.ORDERLIST[START:END+1] If not nodes:return [] if Withscores:return [(X.key, X.score) fo        R x in nodes] Else:return [x.key to X in nodes] def zrevrange (self, start, end, Withscores=false): Card = Self.zcard If End<0:end = end + Card if Start<0:start = start +        Card nodes = Self.slist.orderlist[max (card-end-1, 0): Max (Card-start, 0)][::-1] if not nodes:return []     If Withscores:return [(X.key, X.score) for x in nodes] Else:return [X.key for x in nodes] def zrangebyscore (SELF, start, end, withscores=false): ol = self.slist.orderlist nodes = Ol[bisect_left (OL, start): Bisect_right ( OL, end)] if not nodes:return [] if Withscores:return [(X.key, X.score) for x in nodes] E Lse:return [X.key for X in nodes] def zrevrangebyscore (self, end, start, Withscores=false): return s        Elf.zrangebyscore (Start, End, Withscores) [:: -1] def zincrby (self, key): Snode = Self.slist.key2node.get (key) If not Snode:return self.zadd (key, 1) score = Snode.score Self.zrem (key) return to self. Zadd (key, score+1) Import Contextlibimport timetimeobj = {}class timetrace: @contextlib. ContextManager def mark (self, Name): T = time.time () yield timeobj[name] = Time.time ()-T def stat (self): print '------- --benchmark (100000 requests)---------' for k,v in Timeobj.iteritems (): print ' {} {}s '. Format (k,v) TT = TI Metrace () if __name__ = =' __main__ ': s = SortedSet () s.zadd (' kzc ', +) S.zadd (' A ', 1) s.zadd (' B ', 2) s.zadd (' C ', 2) s.zadd (' d ', 6) S.zadd (' Hello ') s.zadd (' World ') S.zincrby (' Kzc ') print ' KZC score ', S.zscore (' Kzc ') print ' kzc rank ', S.ZR Ank (' kzc ') print ' Kzc Revrank ', S.zrevrank (' Kzc ') print ' Zcount (1,20) ', S.zcount (1,20) print ' Zrange (2,4,withscores =true) ', S.zrange (2,4,withscores=true) print ' Zrangebyscore (1,5,withscores=true) ', S.zrangebyscore (1,5,withscores= True) print ' Zrem ("C") ', S.zrem (' C ') print ' Zrangebyscore (1,5,withscores=true) ', S.zrangebyscore (1,5,withscores=true print ' Zcard ', s.zcard print ' S.zadd ("C", 7) ', S.zadd (' C ', 7) print ' Zcard ', s.zcard print ' Zrevrange all ', S.zrev Range (0,-1,withscores=true) #benchmark import random keys = [STR (x) for x in range (0,100000)] values = Range (0 , 100000) Random.shuffle (keys) with Tt.mark (' Zadd '): Map (lambda x,y:s.zadd (x, y), keys,values) with Tt.mark (' Zscore '): Map (S.zscore,keys) with Tt.mark (' Zrank '): Map (S.zrank,keys) Tt.stat () 

The results are as follows:


Implementation of a Redis zset data structure using Python

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.