2
\$\begingroup\$

This is working but right now it is not giving me the throughput that I want. The main function has the load generation loop (where it is putting work in Queue). I am trying to model a Poisson arrival process for the memcached requests (keys are randomly generated and this is handled in sendRequest). Right now it takes about 3.4 seconds to send (just send, for loop completion) 1000 requests. I want to generate about 30k requests per second or more (adjusting the lambda sleep parameter accordingly).

Is it possible to achieve that speed? What part of this code is limiting the speed of the for loop?

import pylibmc, time, csv
import random, sys, os
import numpy as np
from Queue import Queue
from threading import Thread
import threading
from size_key import size_key #size key is a dict which maps value size to a list of keys

sk=0
sizes=map(str,range(1,1001))
lock=threading.Lock()
nbr_hits=0
rts=0

def sendRequest():
    strt=time.time()
    global sk
    global sizes

    db=pylibmc.Client(["10.2.10.79:21201"]) # port for memcachedb
    mc=pylibmc.Client(["10.2.10.45:11211","10.2.10.47:11211","10.2.10.48:11211","10.2.10.61:11211"])

    r=random.randint(0,999)
    valsize=sizes[r]
    r=np.random.geometric(p=0.1)%len(sk[valsize])
    key=sk[valsize][r]

    val=mc.get(key)
    hit=True
    if val==None: # that means key was not found in memcached
        hit=False
        val=db.get(key)
        mc.set(key,val)

    elapsed=time.time()-strt

    finished(val,elapsed,hit)


def finished(v,rt,hit):
    global lock
    global rts
    global nbr_hits
    with lock:
        rts+=rt
        if hit:
            nbr_hits+=1

concurrent=256
q=Queue(concurrent*2)

def doWork():
    global q
    while True:
        nothing=q.get()
        sendRequest()
        q.task_done()

def main():
    global sk
    global rts
    global nbr_hits
    sk=size_key # same dict as before

    lambd=30000 #inverse of average inter-arrival time, request rate

    sum=0
    start=time.time()

    global concurrent
    global q
    for i in range(concurrent):
        t=Thread(target=doWork)
        t.daemon=True
        t.start()

    print "Started thread pool"
    n=1000
    try:
        st=time.time()
        for i in range(0,n):
            q.put(i)
            wt=random.expovariate(lambd)
            time.sleep(wt)

        et=time.time()-st
        print "Time to send 1k requests:%0.6f"%et
        q.join()
    except KeyboardInterrupt:
        sys.exit(1)

    print "Completed, average latency:%0.6f hit_rate:%0.3f"%(rts/n,float(nbr_hits)/n)
    elapsed=time.time()-start
    print "Time to complete 1k reqs:",elapsed

main()
\$\endgroup\$
  • \$\begingroup\$ Is it possible to post an example for size_key so this script can be tested with real values? \$\endgroup\$ – AlexV Mar 21 '16 at 21:57
  • \$\begingroup\$ I uploaded the size_key dictionary here:dropbox.com/s/czqtwad267rpwvw/size_key.py?dl=0 \$\endgroup\$ – Wajahat Mar 21 '16 at 22:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.