-
Notifications
You must be signed in to change notification settings - Fork 4
Replaced list by queue #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
24790a7 to
2c3bff2
Compare
|
Hi, huge thanks for the changes! I'll take a look at them next week, promise |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@timoxd7
I've measured the performance before and after your change where you replace std::list with std::queue. The code I used for a benchmark was as follows:
for (int i = 0; i < 2'000; i++) {
for (int k = 0; k < 2'000; k++) {
dispatcher.queue(std::string { "123456789123456789123456789123456789123456789" });
}
dispatcher.process();
}Here are the results from multiple runs:
Before your change
Visual C++ 2022 (Debug)
8198 ms
8109 ms
8204 ms
Visual C++ 2022 (Release)
816 ms
775 ms
827 ms
GCC 13 (Debug)
666 ms
665 ms
668 ms
GCC 13 (Release)
240 ms
243 ms
241 ms
After your change
Visual C++ 2022 (Debug)
8566 ms
8459 ms
8503 ms
Visual C++ 2022 (Release)
277 ms
292 ms
275 ms
GCC 13 (Debug)
552 ms
551 ms
553 ms
GCC 13 (Release)
122 ms
121 ms
124 ms
Your changes seem to bring a lot of performance gain. Thank you!
But for future reference, I highly encourage you to always prove that something you claim "should improve performance" indeed works. Compilers are very complicated beasts nowadays and sometimes relying on your intuition can be very deceptive.
Jus by looking at the code I think it's true. It would be nice to have this scenario covered in unit tests though 🙃 |
Ok, will add a test next week, agree |
|
We could also test if the performance might be worse if constantly adding only one element and processing it directly. I think the performance might even be a bit worse than std::list, due to chunk allocation. The std::deque (used by std::queue by default) allocates in chunks, not having to copy elements like a std::vector if needed and still having better cache awareness than a std::list. So it makes it a good fit for queue operations. However, you are right, you never know until you tested it. I just added it for my code and thought it might be useful for you, but did not expect double performance (for your test in release). I like your development style, good testing and you actually measure if something works 😄 |
|
According to your suggestion I modified my benchmark to make a lot of "single queues": for (int i = 0; i < 2'000 * 2'0000; i++) {
for (int k = 0; k < 1; k++) {
dispatcher.queue(std::string { "123456789123456789123456789123456789123456789" });
}
dispatcher.process();
}And the results: It's possible that one element is not enough to trigger a chunk deallocation so it's still faster with |
14e6e16 to
2d2eae8
Compare
|
@KyrietS I just added some commits (sorry for the force pushes, wanted to have a clean history but use GitHub actions for testing). Running some local tests using clang on an arm device and -Os also had some interesting results with your test code. Using all changes from me: Only using the change from std::list to std::queue, but without perfect Forward in queue(...) method: So, the queue has less of an impact as I thought, but the forwarding (which I thought would the compiler optimize to anyway) did the bigger improvement. Maybe in real scenarios, where the nodes of a list might be even farther apart in memory than in the tests, the queue might have a bigger positive impact. Btw, what is going wrong with Visual C++ 2022? 😅 |
KyrietS
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Force-pushing to your own branches is absolutely fine. It's a good sign that you care about git history
In my benchmarks I intentionally used "heavy" event (std::string) with dynamic data to take advantage of your move semantics 😄 Thank you for measuring the impact of the perfect forwarding on performance. You really seem to understand the nuances of C++ 💪
Also, the tests you wrote are exactly how I would have written them myself.
I'm more than happy to merge your changes 🙌
Info
Replaced the list in favour of queue as it is perfectly made for this use-case. Should improve performance.
Also, this allows to queue new elements inside a queueDispatch callback.
Btw, thanks for this lib, had exactly this in mind and found it then, saved me a ton of work.