Rocco Caputo wrote:
On Tue, Feb 10, 2004 at 09:00:01PM -0800, Scott wrote:Only two, relatively minor things.
Rocco Caputo wrote:
I'm glad you don't support inter-session calling. You really can't do that without at least setting POE::Kernel's notion of the active session. Otherwise a callee's alarms (and other resources) will be associated with the caller session. That's obviously wrong.
Thats only reason #1 I dont support inter-session calling.
Reason #2 is that I dont even agree call() should be performed inter-session.
[lots of good stuff removed; go back and read it]
And that was the reason I didn't understand why Kernel->call() was faced with so much overhead, of course that is until I realized, it really shouldn't be using _dispatch_event() but it had to, because inter-session calling was permitted. So garbage collection routines and etc were absolutely neccesary. In fact, there isn't much that Kernel->call() does that isn't neccesary aside from a few bitwise operations to determine the current type of event and the neccesary course of action. But much of the overhead of Kernel->call() was easily disposable by disallowing inter-session calls.
Because a serious API change, such as changing the arguements to an existing method or subroutine (for instance, removing the session arguement from Kernel->call()) is difficult to accomidate, I was greatly in favor of the RFC for Revising call.
Unfortunately, the nature of ->call() makes me think it should in fact
be a Kernel method, however that kernel method already exists and is
flawed for the above noted reasons. And this is the rational for
adding a call() method to POE::Session.
Hmm... is there anything stopping you from patching POE::Kernel::call()
to check the resolved destination session against the caller session,
and bypassing _dispatch_event() if they're the same?
First being that I wanted to deprecate the interface for Kernel->call(), ommiting the session parameter as it should be unneccesary.
Second being I was following the revision pattern noted in the wiki.
That suggestion would work perfectly fine as an optimization, but I think the call() method needs revised entirely.
Personally, I look at POE's Sessions in light of Knuth's co-routines.
Since we aren't coding in assembler, we cant actually implement Knuth's
co-routines but Sessions are practically the same thing (Only on a larger scale).
call() exists to avoid race conditions, to get things NOW. I don't think call
should be done inter-session, just as one shouldn't delve into the contents
of an external object. Thats what the public interfaces are for. Also, in
light of the co-routines, inter-session communication should be done via
post(), in order to return processing to the system core, so it can delegate
the next event appropriately.
- Scott.
(Trying anxiously to being a discussion on the mailing list... ;))
Here too. Thanks for reposting it.
In addition, there are several optimizations that cannot be made from POE::Kernel->call,
one is that due to the current interface rules we must allow Kernel->call() to be given
the arguement of a session id or alias. For this reason, we must resolve the first arguement
to the appropriate session. Thats not the case with adding a call() routine to POE::Session
as we are guarenteed a POE::Session object. So we simply cannot do the same amount
of optimization.
My tests show that performing this optimization only provides 1/2 the speed increase
the Session->call method did:
(Optimized) POE::Kernel->call(): 34 wallclock secs (33.82 usr + 0.01 sys = 33.83 CPU) @ 29559.56/s (n=1000000)
(Old) POE::Kernel->call(): 48 wallclock secs (46.80 usr + 0.35 sys = 47.15 CPU) @ 21208.91/s (n=1000000)
POE::Session->call(): 22 wallclock secs (21.64 usr + 0.01 sys = 21.65 CPU) @ 46189.38/s (n=1000000)
Attached is the patch that performs this optimization to POE::Kernel.
Aside from that, there was a second rational behind POE::Session->call(), and that is, to provide an interface for a higher level of event routing. One that bypasses the POE::Kernel entirely, but still respects ->state() changes. Its a middle ground between invoking the code reference the state actually resolves to directly, and actually throwing an event to the Kernel.
The idea being optimizations such as, switching the event handler via POE::Kernel->state() would still work, and we still have the advantage of a live, active @_ being built by POE::Session's _invoke_state(), but since we're not actually an event we don't need the FIFO, and since we're obviously not changing sessions we dont need GC'd, and since we know who we are we dont need any resolution. This makes doing your event routing entirely external from POE less favorable for components, for instance. Where a common practice is currently to accept code references in the constructor. Here we could actually just as easly, without a great efficiency loss, accept event names and allow the user to contribute to the session's construction. This adds, in addition to the above noted benefits, the ability to easily design state-type free components. In which case I mean, a component that simply accepts the same inline_state, package_state, and object_state arguements that POE::Session's constructor does, and allows the user to build their session's events in which ever way they see fit. Without being horribly inefficient by say, making every single little tiny event hit the fifo or traverse _dispatch_event in any way.
Some of us try to build our components to be as efficient as possible, doing things like multiplexing our sessions to avoid needing a seperate session for each task, and routing our interface events with code references instead of POE itself. This makes it easier for us to provide beautiful interfaces to components that are still relatively fast.
- Scott
