majek / puka

Puka - the opinionated RabbitMQ client
https://github.com/majek/puka
Other
181 stars 34 forks source link

Unexpected: synchronous publishing without pub confirms is slower than with confirms #60

Open vitaly-krugl opened 9 years ago

vitaly-krugl commented 9 years ago

Running both RabbitMQ 3.5.1 and test app on my recent model development MacBookPro (OS X Yosemite), I encountered unexpected, reproducible performance conundrum: with pubacks=False, synchronous publishing is consistently slower than with pubacks=True. This is counterintuitive and differs from all other AMQP clients that I profiled.

I used the apps from https://github.com/vitaly-krugl/amqp-perf to profile basic_publish performance. Below are a few examples of what I am talking about.

puka with pubacks=False

I verified that the channel IS NOT in confirm mode

time python puka_perf.py publish --impl=Client --exg="" --size 1024 --msgs=100000

real    0m22.728s
user    0m12.593s
sys 0m2.129s

puka with pubacks=True

I verified that the channel IS in confirm mode

time python puka_perf.py publish --impl=Client --exg="" --size 1024 --msgs=100000 --delivery-confirmation

real    0m17.368s
user    0m9.054s
sys 0m2.112s

Here, you can see that both real and user execution times are smaller for pubacks=True. This is unexpected, because with pubacks=True the broker needs to check whether the exchange exists before it can Ack, whereas with pubacks=False, the broker can Ack right away.

Below are a couple of comparable tests and corresponding execution times for haigha:

haigha with pubacks=False

time python haigha_perf.py publish --impl=SocketTransport --exg="" --size 1024 --msgs=100000

real    0m10.010s
user    0m7.772s
sys 0m2.231s

haigha with pubacks=True

time python haigha_perf.py publish --impl=SocketTransport --exg="" --size 1024 --msgs=100000 --delivery-confirmation

real    0m21.344s
user    0m13.371s
sys 0m3.531s
majek commented 9 years ago

Puka treats your message delivery serious.

When you publish with pubacks=False, what do you actually mean by saying "synchronous"? Usually people mean: being sent off the networks. For puka this is not enough and it actually tries to synchronize with the server to make sure it was indeed delivered. That means that publishing in pubacks=False mode is two operations: async publish followed by sync something to synchronize.

If you wish higher speed with pubacks=False, please send many messages, gather a number of promises and wait for them all at once.

vitaly-krugl commented 9 years ago

Sorry @majek, let me rephrase: I meant "blocking" via client.wait(client.basic_publish(...). My understanding is that to "synchronize", the client library waits for Basic.Ack in the case of pubacks=False. In the case of of pubacks=True, the client library also waits for Basic.Ack (or the very rare Basic.Nack) and an optional Basic.Return may occur prior to Basic.Ack if the the message was undeliverable.

So, in both scenarios pubacks=False/True, the client library needs to wait for Basic.Ack in order to synchronize with the server. What else does the client library need to do to synchronize with the broker? Thus, it's intuitive to expect that the no-confirms case would be faster than the confirms case, even if sending messages one-at-a-time.

majek commented 9 years ago

hmm

If pubacks=True puka uses publisher acks to synchronize. If pubacks=False puka uses some other obscure mechanism to synchronize, since publishes are asycn.

vitaly-krugl commented 9 years ago

I see, in the pubacks=False case, it "guards" the original message with another message that's guaranteed to be returned:

        eheaders = {'x-puka-delivery-tag': delivery_tag, 'x-puka-footer': True}
        frames = frames + \
                 spec.encode_basic_publish('', '', True, False, eheaders,
                                                '', conn.frame_max)

@majek, My app uses two types of AMQP messaging with respect to delivery guarantees:

  1. Guaranteed delivery of ordered data; relies on publisher acknowledgments with mandatory=True and basic.return support for at-least-once delivery guarantee;
  2. Notifications; prefers speed and no need for guaranteed delivery

For the second scenario, is there a way to configure a puka Client that would disable the extra overhead of the x-puka-delivery-tag business? There are usage scenarios where these "guard" messages are a detractor.

@majek, I am looking for alternatives to my current AMQP client due to licensing incompatibilities, and would like to make an informed decision. In the README, it states

Puka is experimental ... Puka is a side project, written mostly to prove if it is possible to create a reasonable API on top of the AMQP protocol.

Does the above quote mean that there is no motivation to maintain it and that it would be a non-starter for use in production? What is your recommendation? Are a lot of people using it? If I switch to puka, I will be motivated to contribute, but I want to make sure that it's already stable before making the move.

Many thanks, Vitaly