Re: Do events due to yield have higher precedence than those due to delay for kernel dispatch?
Rocco Caputo <[email protected]> Thu, 12 Jul 2012 01:55:06 -0400
| Newsgroups | gmane.comp.lang.perl.poe |
|---|---|
| Message-ID | <[email protected]> |
Hi, Deven. It appears that you expect event handlers to run concurrently, which = they don't. Event handlers are run sequentially, in order of dispatch = due time. In other words, each is allowed to finish before the next is = dispatched. post() and yield() events are dispatched "as soon as possible". To keep = things fair, they are given the dispatch time of Time::HiRes::time(), = which enqueues them ahead of future timers, or behind timers that are = overdue. For example, you may have a queue of events scheduled for absolute times = 10, 20, and 30 seconds from some epoch boundary. We'll call the events = e_10, e_20, and e_30, respectively. At dispatch time, all events due prior or equal to "Now" are dispatched. = If none are due, the event loop POE is using will be asked to wait = until the next one is due. For example, POE's default event loop uses select(). If the current = time is 5, the select() call will time out in 10-5 seconds, give or take = processing time. If there is no I/O for 5 seconds, select() returns, = and e_10 is dispatched on schedule. Event handlers take some measurable time to execute. The faster, the = better, but many use cases can handle substantial processing delays. Let's assume the handler for e_10 takes 15 seconds to run. The next = event (e_20) won't be dispatched until about 25 seconds past the start = of the epoch. That's 5 seconds later than it was scheduled. In your test case, the 1/4-second processing time for each event handler = means that only 3-5 of them can be dispatched every second. You will = need to make the time-consuming tasks asynchronous or distribute the = work across more cores. --=20 Rocco Caputo <[email protected]> On Jul 12, 2012, at 01:13, Deven Parekh wrote: > Hello POE team, >=20 > I am trying to understand if the POE kernel dispatching algorithm has = any > precedence when it comes to events from yield Vs events from delay. = Please > read through the email to see if you can help me figure out what is = the > mistake i am doing here. >=20 > Following is the code snipett that demonstrates my issue. >=20 > <code> > #!/usr/bin/perl > use strict; > use warnings; > use Algorithm::TokenBucket; > use Time::HiRes; > use POE; > use POE::Component::Schedule ; >=20 > my $so_many_task =3D 10; > my $so_many_seconds =3D 1; > my $burst_size =3D 1; > my $stop =3D 0; >=20 > my $bucket =3D new Algorithm::TokenBucket $so_many_task / = $so_many_seconds, > $burst_size; >=20 > my $time =3D Time::HiRes::time; > my $master_session =3D POE::Session->create( > inline_states =3D> { > _start =3D> \&master_start, > put_one_on_queue =3D> \&put_one_on_queue, > generate_tick =3D> \&generate_tick, > next_task =3D> \&next_task, > stop_scheduling =3D> \&stop_scheduling, > _stop =3D> sub { }, > dummy =3D> sub { }, > } > ); >=20 > POE::Kernel->run(); > exit(0); >=20 > sub master_start { > my $kernel =3D $_[KERNEL]; > $_[KERNEL]->alias_set("Enqueuer"); > $_[KERNEL]->yield("generate_tick"); > $_[KERNEL]->delay( "stop_scheduling" =3D> 1 ); > } >=20 >=20 > sub generate_tick { > my $kernel =3D $_[KERNEL]; > if ( $stop =3D=3D 0 ) { > my $after_sec =3D $bucket->until($burst_size); > print "Next one after $after_sec\n"; > $_[KERNEL]->delay_add( "put_one_on_queue" =3D> $after_sec ); > } > } >=20 > sub stop_scheduling { > print "Stopped \n"; > } >=20 > sub put_one_on_queue { > my $kernel =3D $_[KERNEL]; > if ( $bucket->conform($burst_size) ) { > print Time::HiRes::time -$time, " - Processed $burst_size more = \n"; > $bucket->count($burst_size); > $_[KERNEL]->yield("generate_tick"); > $_[KERNEL]->yield("next_task"); > } > } >=20 > sub next_task { >=20 > #--- some operation that is taking about 0.2 sec > #--- using select to show it here. >=20 > #print "Started next task\n"; > select( undef, undef, undef, 0.25 ); > #print "Done with next task\n"; > } >=20 > </code> >=20 > <p> > With the above code and the select statement, which i amusing to = simulate > some operation taking about .25 seconds, the output is as follows >=20 > [lss@ctsauto1 misc]$ ./atbkt_2.pl > Next one after 0.0995830059051514 > 0.100232124328613 - Processed 1 more > Next one after 0.0998860359191895 > 0.350847959518433 - Processed 1 more > Next one after 0.0998910427093506 > 0.60145115852356 - Processed 1 more > Next one after 0.0998910427093506 > 0.852055072784424 - Processed 1 more > Next one after 0.0998538494110107 > 1.10269498825073 - Processed 1 more > Stopped >=20 > *Well i was expecting 10 items to be processed in 1 second not just = 5.* >=20 >=20 > Now if i comment the select statement in the next_task routine then I = get > following output. >=20 > Next one after 0.0997329711914063 > 0.100254058837891 - Processed 1 more > Next one after 0.0999299049377441 > 0.200562953948975 - Processed 1 more > Next one after 0.0999120235443115 > 0.300816059112549 - Processed 1 more > Next one after 0.0999170303344727 > 0.401067018508911 - Processed 1 more > Next one after 0.0999160766601563 > 0.501316070556641 - Processed 1 more > Next one after 0.0999160766601563 > 0.601574897766113 - Processed 1 more > Next one after 0.0999120235443115 > 0.701813936233521 - Processed 1 more > Next one after 0.0999158382415772 > 0.802061080932617 - Processed 1 more > Next one after 0.0999151229858398 > 0.902349948883057 - Processed 1 more > Next one after 0.0999170303344727 > Stopped > 1.0025269985199 - Processed 1 more >=20 > *10 items in 1 second as expected.* >=20 >=20 > Any help will be greatly appreciated. >=20 > Thanks. > -- DP