On 3/8/13 3:19 PM, Rafael Schloming wrote:
On Thu, Mar 7, 2013 at 5:15 AM, Bozo Dragojevic <bo...@digiverse.si
<mailto:bo...@digiverse.si>> wrote:
On 3/6/13 3:45 AM, Rafael Schloming wrote:
Oops, meant to send this to the list.
---------- Forwarded message ----------
From: Rafael Schloming<r...@alum.mit.edu <mailto:r...@alum.mit.edu>>
Date: Tue, Mar 5, 2013 at 6:44 PM
Subject: Re: put vs. send
To: Bozo Dragojevic<bo...@digiverse.si
<mailto:bo...@digiverse.si>>
[snip]
Thank you for taking the time to explain, that's very helpful. It
makes me wonder if we shouldn't include some kind of
pn_messenger_interrupt() that to pull out of blocking calls early.
That'd be great!
Few weeks ago I've submitted
https://issues.apache.org/jira/browse/PROTON-231
for this feature and the JIRA has a link to my attempt at implementation
(based off 0.3 branch) -- this is what we use now.
I've named it pn_messenger_wakeup() after pn_driver_wakeup() that it calls.
In addition the pn_messenger_tsync() needed to be adjusted to actually
exit early :)
So for me this opens up two new areas (one of the reasons it took
me a bit to reply):
- study up the API on 'trackers',
iiuc thats the name of what pn_messenger_put() returns
- figure out how to use them inside our code so that
the publisher (API user) will not drown itself in messages
it cannot realistically send.
I'm not sure trackers are what you want here (although it may be
depending on your app). Trackers are used to track the status of the
message at the receiver, e.g. it will tell you whether the receiver
has accepted or rejected the message.
the fourth paragraph below circles back to trackers :)
If you just care about limiting the rate of your producer to match
what you can actually push onto the wire, then you can just look at
pn_messenger_outgoing(), that will tell you how many messages are
actually backed up waiting to go onto the wire, e.g. before or after
doing a put/send/recv/etc, you can check the size of the outgoing
queue and based on that decide whether you need to throttle your producer.
Looking at total size of outgoing queue is sufficient for the messenger
that is
part of the application that acts as the publisher and sends messages to the
broker as it then has just one peer.
The scenario that is important is this: Broker, too, wants to rate-limit
each peer
based solely on that peer's capability to receive messages. So if there
are two
subscribers and one is on a slower link, or is not behaving in some
other way,
then the fast subscriber should not be held hostage of the slow subscriber.
This is even more so if we're talking about two publishers each having a
set of own subscribers.
On the messenger level, the broker ends up having a bunch of amqp
addresses where
the message received from the publisher need to be forwarded.
The answer that is sought is pn_messenger_outgoing(address). Now, a
tracker does
uniquely identify the remote address that is embedded in the message
being sent.
If there is/were a query of local messenger's opinion on progress status
wrt.
delivering of that one message where one distinct answer would be
"managed to put it on the wire".
A function like that makes it trivial for a messenger user (broker) to
perform
the accounting of 'number of outstanding messages per address' on it's own.
- ability to spread out load of serialization and deserialization
over cores
and as mentioned above there are two 'layers' of it:
bytes <=> pn_message <=> API object
Providing this within the messenger paradigm sounds tricky to me
-- I definitely don't want messenger to grow it's own thread
pool :)
This sounds to me like it could possibly be addressed by a smarter
pn_message implementation. Right now pn_message_t is implemented in a
very basic way where it actually does a lot of unnecessary
encode/decode work. Not only could that be made more efficient so
there is much less load to be distributed, but it could also be made
to happen on demand. That would give you the flexibility of hitting
most of the cost of the bytes <=> pn_message_t portion in whichever
thread you chose.
This multi-core business obviously makes most sense for cases where
there is more
than one TCP connection where data flows in.
The thread that read a bunch of bytes from a socket already has them in
that CPU cache.
Doing as much of the work with those bytes on that CPU, without context
switches,
will be fast.
- more control over IO and waiting (as per description above)
this alone would still fit into your proposed extension quite nicely
In the other thread you mention bringing send() and recv()
closer wrt meaning of
a parameter.
It'd be a tiny step from there to provide a sync(send_limit,
recv_limit)
which would help me in reasoning of there being exactly one path
that ends up
in pn_driver_wait() -- this would simplify interactions between
- ability to maybe (ab)use several TCP connections for sending of
messages
with different latency-sensitive information
This one is more a possible solution than a requirement
What would be sufficient from interface perspective is to have
ability for
messages (potentially to the same destination) to jump the
queue, so to speak,
but this could potentially still fit within the messenger paradigm
This is an interesting one AMQP does provide a priority header on the
message that is a clue that ordering is relaxed. Right now neither
messenger nor the engine pays any attention to it though. As an
interface it seems like the obvious thing, however implementation of
it might be interesting.
Thanks,
Bozzo