fix(python): use deque for insert-order message queue #1316
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Changelog
Significantly increases the performance of iterating through an MCAP file in insertion order.
Docs
None. (internal only)
Description
I used
iter_messages(log_time_order=False)
since my application doesn't care about message order, expecting it to perform better thanlog_time_order=True
(the default). However I noticed that my application took 17 minutes to iterate through 3.5 million MCAP messages. It took 32 seconds withlog_time_order=True
.The previous message queue implementation used a
list
as a FIFO queue, which has poor performance aspop(0)
will copy the list every time an item is evicted. After changing the implementation to use adeque
,log_time_order=False
took 15 seconds.Here's code for a minimal performance test. Note that the mcap file has ~3.5 million messages.
Note that
deque(iterable, maxlen=0)
will consume the iterable in C, so basically as fast as possible (see theitertools
recipe forconsume()
).I ran this three times after the fix, but just once before because I didn't have the patience 😄
10.840037822723389
10.490556001663208
Over 100x faster! If you're curious,
log_time_order=True
was ~17 seconds (both before and after the changeset).I also updated the code to have two separate impls rather than a bifurcated implementation.
I added a unit test to assert that
log_time_order=False
is faster thanTrue
(purposely adding messages in reverse log time order so that the heap should perform worse). As with most perf unit tests, it is potentially flakey with smaller inputs so I put 10k messages in it, but feel free to discuss if there's a different way you want to run through that.