issue #155: allocate child IDs in batches of 1000.

Avoids a roundtrip for every fork.
pull/167/head
David Wilson 6 years ago
parent 0c77107041
commit f4ba66e3ee

@ -724,16 +724,25 @@ class IdAllocator(object):
finally:
self.lock.release()
def allocate_block(self):
self.lock.acquire()
try:
id_ = self.next_id
self.next_id += 1000
return id_, id_ + 1000
finally:
self.lock.release()
def on_allocate_id(self, msg):
if msg == mitogen.core._DEAD:
return
id_ = self.allocate()
id_, last_id = self.allocate_block()
requestee = self.router.context_by_id(msg.src_id)
allocated = self.router.context_by_id(id_, msg.src_id)
LOG.debug('%r: allocating %r to %r', self, allocated, requestee)
msg.reply(id_)
LOG.debug('%r: allocating [%r..%r) to %r', self, allocated, requestee)
msg.reply((id_, last_id))
LOG.debug('%r: publishing route to %r via %r', self,
allocated, requestee)

@ -37,6 +37,7 @@ import socket
import sys
import termios
import textwrap
import threading
import time
import zlib
@ -423,12 +424,24 @@ class Stream(mitogen.core.Stream):
class ChildIdAllocator(object):
def __init__(self, router):
self.router = router
self.lock = threading.Lock()
self.it = iter(xrange(0))
def allocate(self):
master = mitogen.core.Context(self.router, 0)
return master.send_await(
mitogen.core.Message(dst_id=0, handle=mitogen.core.ALLOCATE_ID)
)
self.lock.acquire()
try:
for id_ in self.it:
return id_
master = mitogen.core.Context(self.router, 0)
start, end = master.send_await(
mitogen.core.Message(dst_id=0, handle=mitogen.core.ALLOCATE_ID)
)
self.it = iter(xrange(start, end))
finally:
self.lock.release()
return self.allocate()
class Router(mitogen.core.Router):

@ -8,8 +8,20 @@ import id_allocation
class SlaveTest(testlib.RouterMixin, testlib.TestCase):
def test_slave_allocates_id(self):
context = self.router.local()
# Master's allocator named the context 1.
self.assertEquals(1, context.context_id)
# First call from slave allocates a block (2..1001)
id_ = context.call(id_allocation.allocate_an_id)
self.assertEqual(id_, 2)
# Second call from slave allocates from block (3..1001)
id_ = context.call(id_allocation.allocate_an_id)
self.assertEqual(id_, self.router.id_allocator.next_id - 1)
self.assertEqual(id_, 3)
# Subsequent master allocation does not collide
c2 = self.router.local()
self.assertEquals(1002, c2.context_id)
if __name__ == '__main__':

Loading…
Cancel
Save