server blocks on fast method while slow method is being executed.

79 views
Skip to first unread message

Shiplu Mokaddim

unread,
Mar 16, 2018, 1:25:33 PM3/16/18
to zerorpc
I have this server


import zerorpc
import time


class MyServer(object):
    def fast(self):
        return 'FAST'

    def slow(self):
        for i in range(5):
            time.sleep(1)
            zerorpc.gevent.sleep(0)
        return 'SLOW'

server = zerorpc.Server(MyServer(), heartbeat=None)

server.bind("tcp://0.0.0.0:9999")


try:
    zerorpc.gevent.spawn(server.run)
    while True:
        zerorpc.gevent.sleep(1)
except KeyboardInterrupt:
    print("KeyboardInterrupt Received!")
    server.close()


Now if I call slow first then fast, then fast is blocked for whole run time of slow. See this

$ zerorpc tcp://0.0.0.0:9999 slow & time zerorpc tcp://0.0.0.0:9999 fast;
[1] 31651
connecting to "tcp://0.0.0.0:9999"
connecting to "tcp://0.0.0.0:9999"
'FAST'
'SLOW'
[1]+  Done                    zerorpc tcp://0.0.0.0:9999 slow

real 0m5.072s
user 0m0.084s
sys 0m0.044s

Steps
1. slow is executed in the background
2. fast is executed wrapped with time
3. Both connect at the same time
4. fast is BLOCKED
5. fast is done
6. fast prints is result
7. slow prints its result

We can see fast executed for 5 seconds. But in slow function zerorpc.gevent.sleep(0) was executed every 1 seconds.

1. shouldn't fast return just after 1 second?
2. How can I make sure fast is not blocking while slow is being executed?

François-Xavier Bourlet

unread,
Mar 16, 2018, 4:59:53 PM3/16/18
to zer...@googlegroups.com
replace time.sleep(1) by gevent.sleep(1)

In your case, gevent.sleep(0) yields control back to the ioloop, which in turn let zerorpc run a bit, before getting back to your time.sleep(1).

zerorpc depends on gevent, and thus requires you to be cooperative.

When you call time.sleep(1) you block your thread for a second. During this time, nothing happens. Gevent ioloop is not running.
--
You received this message because you are subscribed to the Google Groups "zerorpc" group.
To unsubscribe from this group and stop receiving emails from it, send an email to zerorpc+u...@googlegroups.com.
To post to this group, send email to zer...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/zerorpc/7ffb8462-0e25-4895-80ab-cf03eb5d6e25%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Shiplu Mokaddim

unread,
Mar 16, 2018, 6:45:21 PM3/16/18
to zerorpc
By time.sleep(1) I meant a time-consuming task. In my actual code I am polling few python multiprocessing.Queue. 

It's more like:

while True:
  # check queue 1
  gevent.sleep(0)
  # check queue 2
  gevent.sleep(0)
 

But it seems, these 2 calls are not enough. I can not actually monkey patch the thread as it has issues with multiprocess.Queue. See http://www.gevent.org/gevent.monkey.html#gevent.monkey.patch_thread


In the example, I yielded only once in a loop. Correct me if I am wrong, it seems ZeroRPC executed too little which was not enough to call my `fast` function.

How can I make sure if another function is waiting to be called that will be called?

Shiplu Mokaddim

unread,
Mar 16, 2018, 7:08:19 PM3/16/18
to zerorpc
Seems like I found a way.

Instead of using gevent.sleep(0) I used gevent.sleep(0.1). So a bit more time for ZeroRPC to let it call my function.
0.01 works too. But it increases wait time. So I have to find a balance.
Reply all
Reply to author
Forward
0 new messages