Okay, I am no POE internal genius, and perhaps I am using call() inappropriately (inter-session), but I find a lot of convenience in using a separate Session to hold data that needs to be synchronized/serialized. Not only that, that there is also even greater convenience in that fact that call() returns something. I don't need to provide or kludge around with return events for data that I need immediately for critical paths. Now some may argue that I just need to maintain a separate class or object and make method calls to that to access that data, but then I run into the problem of making sure all the Sessions that I want to be able to access that object, all have that object. With a stand alone Session, I can simply reference it by its alias and make call()s to it. Now maybe the negatives outweigh my laziness, but in my not so knowledgeable opinion, having a specific Session filled just with synchronized or critical functions just makes sense in the cases that I have applied it.

Just my two cents on the matter. I found a practical application for what everyone seems to call ugliness.

Scott wrote:

Scott wrote:

Rocco Caputo wrote:

On Tue, Feb 10, 2004 at 09:00:01PM -0800, Scott wrote:


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?


Only two, relatively minor things.

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

Reply via email to