-
Notifications
You must be signed in to change notification settings - Fork 103
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
Arguments are copied unnecessarily #18
Comments
Thanks for the detailed report. I agree that the current implementation is not optimal with respect to arguments forwarding. The first part of your suggested fix is simple to apply, and will avoid one copy for rvalues. The second part is considerably trickier, as it involves forwarding arguments to a virtual method (call_slots). I will look into it. |
So, I had an idea for a quick-fix by performing a conditional move depending on the type of each argument to It appears to pass all the unit tests but I will a to test some corner cases. Copy-only and rvalue reference arguments come to mind. Do tell me if this is what you had in mind. |
@palacaze Sorry for the slow answer. That's what I had in mind! Some feedback on the perf branch:
Would you prefer to implement this yourself or take a PR from me? I'm on vacation next week but could potentially work on it after. |
Yes, this seems to give the same result. maybe_move uses explicit casting whereas std::forward relies on reference collapsing. Using std::forward crossed my mind but this is not a customary use for it, and I worried it would not convey the semantics correctly.
Two trade-offs for groups right now to minimize connection and disconnection costs is to keep an ordered vector or groups, and also to keep empty groups. This was the easy to implement and signal emission was not really impacted. Consequently, I cannot rely on iteration because the last group may very well be empty. Another possible implementation may be to keep a single vector with all the slots, weakly ordered by group_id. Connections and disconnections will be more expensive, but signal emission will be more straightforward and maybe cheaper. The reason why I avoided this design is to avoid pulling the algorithm header. Maybe I should revisit this design choice.
|
I forgot to reply to your question. This is my last day of vacation and I may not have a lot of time to work on this in the next few weeks. So, yes, I would not happily accept a PR. One thing I want to do soon is to setup a CI, because this is becoming tricky to test for regressions on multiple platform and OS combinations. |
You mean you'd accept a PR, right? 😄 |
Yes, sorry... |
As would I, thanks for the reminder! |
Thanks for the great library!
I recently noticed that value arguments (e.g.,
signal<std::string>
, notsignal<const std::string&>
) are not passed optimally with regards to moves/copies. As shown in the test below, there are some unnecessary copies. IfCopyCounter
were replaced with a largestd::vector
, this could be a performance problem.I believe one fix would be to use
std::forward
for arguments insignal_base::operator()
, to onlystd::forward
arguments for the last slot inslot_base::operator()
, and tostd::forward
(notstd::move
) arguments inslot*::call_slot
. A stack overflow answer has some information about only forwarding the last slot's args.It would be possible to go further and also eliminate copies for non-movable types, but may not be worth the complexity.
The text was updated successfully, but these errors were encountered: