Conversation
|
Hi! Thanks for your PR. I think this is a step towards the right direction. I am not convinced about the heuristic to determine whether we memmove or not though. Consider:
So I'm not convinced about the actual packet size being predictable. I think that this approach is working well for the I'd explore the possibility of approaching this as a cost/benefit analysis, instead. If we decide to memmove, we gain
We also need to consider the buffer's limit size. A message that fits the limit shouldn't cause an error, regardless of how many bytes we had in the reserved area. Thanks for working in this. Let me know if you need aky help. Regards, |
|
Thanks for the review! You are right: trying to calculate average message size is unsuitable when working with MySQL protocol and connection pools. I pushed new solution that following your suggestions:
However, the benchmark aren't showing that improvement as my previous suggestion. I did some more investigation and that's why it happened: My previous EMA-based solution would trigger a reallocation that allocated a buffer larger than the incoming row size. This extra size allowed to avoid additional memmoves. However, in the standard |
|
This looks more sound to me, thanks. The "would prevent reallocation condition" seems to be missing a piece. We're currently checking that the required space is greater than I think what you propose in #502 is sound. Do you want to implement it as part of this PR? Thanks, |
|
If requested size is big enough to still cause reallocation, then by compacting the buffer we reduce reallocation cost. That's why it seems quite logical for me. Yes, I would love to implement #502 proposal in this PR. |
Fair. Go ahead with this approach. |
|
Combined, these changes reduce |
|
Looks good. A couple of comments:
|
|
Yes, there is performance difference. Since that template implementation is branchless, it's a lot faster, see: I will come back later with new unit tests! |
|
Added new unit tests and overflow assertation in |
| constexpr std::size_t num_tests = sizeof(test_sizes) / sizeof(test_sizes[0]); | ||
|
|
||
| // Test that buffer capacity grows to powers of two | ||
| for (std::size_t i = 0; i < num_tests; ++i) |
There was a problem hiding this comment.
Can we use range for here?
|
Thanks for this, it's looking really good! |
|
Done! |
|
Could you please merge develop into this and the other PR so we get the coverage report? |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #501 +/- ##
========================================
Coverage 99.15% 99.16%
========================================
Files 144 145 +1
Lines 7370 7387 +17
========================================
+ Hits 7308 7325 +17
Misses 62 62
Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
|
Merged! Thanks a lot for working on this. |
Solves #462
Instead of memmove everything on every call to
message_reader::prepare_buffer(), we can use Exponential Moving Average (EMA) formula to predict next message size. If predicted message size fits into buffer, we can avoid memmove.Callgrind screenshots (boost_mysql_bench_one_big_row_boost)
Before:Before:
Total instructions - 1184758337
Memcpy instructions - 1030331155
After:
Total instructions - 154287054 (x7.6 less)
Memcpy instructions - 485896 (x2120 less)
It's almost free EMA implementation with high predictive power.