Skip to content

Instantly share code, notes, and snippets.

@ThiefMaster
Last active April 19, 2017 21:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ThiefMaster/5370986 to your computer and use it in GitHub Desktop.
Save ThiefMaster/5370986 to your computer and use it in GitHub Desktop.
local avatar = ARGV[1]
local user_events = redis.call('ZRANGE', 'user_events:'..avatar, 0, -1)
local res = {}
for i, event in ipairs(user_events) do
res[event] = redis.call('SMEMBERS', 'user_event_roles:'..avatar..':'..event)
end
return cjson.encode(res)
import itertools
import ujson
import redis
import random
from collections import defaultdict
from contextlib import contextmanager
from datetime import datetime
MIN_TIME = 978328800 # 2001/1/1 00:00:00
MAX_TIME = 1388555999 # 2013/12/31 23:59:59
@contextmanager
def timing(what):
start = datetime.utcnow()
yield
duration = (datetime.utcnow() - start).total_seconds()
print 'Execution time: %0.5fs (%s)' % (duration, what)
class Avatar(object):
def __init__(self, id_):
self.id = id_
self.linked_to = defaultdict(set)
def link_to(self, role, event):
self.linked_to[role].add(event)
def unlink_to(self, role, event):
self.linked_to[role].remove(event)
def init_redis_linked_to(self, client):
all_events = set(itertools.chain(*self.linked_to.itervalues()))
for event in all_events:
client.sadd('event_users:%s' % event.id, self.id)
zdata = {str(e.id): e.ts for e in all_events}
client.zadd('user_events:%d' % self.id, **zdata)
event_roles = defaultdict(set)
for role, events in self.linked_to.iteritems():
for event in events:
event_roles[event].add(role)
for event, roles in event_roles.iteritems():
client.sadd('user_event_roles:%d:%d' % (self.id, event.id), *roles)
def __eq__(self, other):
return isinstance(other, type(self)) and self.id == other.id
def __repr__(self):
return 'Avatar(%d)' % self.id
class Event(object):
def __init__(self, id_, ts):
self.id = id_
self.ts = ts
def __eq__(self, other):
return isinstance(other, type(self)) and self.id == other.id
def __repr__(self):
return 'Event(%d, %d)' % (self.id, self.ts)
if __name__ == '__main__':
client = redis.StrictRedis(password='12345')
INIT = False
NUM_EVENTS = 10000
NUM_AVATARS = 1000
MAX_USER_EVENTS = 250
UID = 666 # user id to retrieve data for
if INIT:
client.flushdb() # XXX DANGER XXX
print 'Generating events'
events = [Event(eid, random.randrange(MIN_TIME, MAX_TIME)) for eid in xrange(NUM_EVENTS)]
print 'Generating avatars'
avatars = [Avatar(aid) for aid in xrange(NUM_AVATARS)]
print 'Linking events/avatars'
for avatar in avatars:
for i in xrange(random.randint(1, MAX_USER_EVENTS)):
avatar.link_to(random.choice(['manager', 'speaker']), random.choice(events))
print 'Storing data in redis'
with client.pipeline(transaction=False) as pipe:
for avatar in avatars:
#print avatar, avatar.linked_to
avatar.init_redis_linked_to(pipe)
pipe.execute()
else:
print 'Pure python:'
with timing('total'):
with timing('fetch from redis'):
eids = [unicode(eid) for eid in client.zrange('user_events:%d' % UID, 0, -1)]
with client.pipeline(transaction=False) as pipe:
for eid in eids:
pipe.smembers('user_event_roles:%d:%s' % (UID, eid))
res = pipe.execute()
with timing('convert to dict'):
final_1 = dict(zip(eids, [[unicode(role) for role in roles] for roles in res]))
print
print 'LUA prodecure:'
with timing('total'):
client.script_flush()
with open('get_user_linked_events.lua') as f:
get_user_linked_events = client.register_script(f.read())
with timing('fetch from redis'):
res = get_user_linked_events(args=[UID])
with timing('decode json'):
final_2 = ujson.loads(res)
print
print 'Consistent results? %s' % (final_1 == final_2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment