-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
[core] Pass TString by value to TNamed ctor #15469
base: master
Are you sure you want to change the base?
[core] Pass TString by value to TNamed ctor #15469
Conversation
Test Results 11 files 11 suites 2d 16h 17m 3s ⏱️ Results for commit 2bafc6e. ♻️ This comment has been updated with latest results. |
e11f5e2
to
03038d2
Compare
TNamed(const char *name, const char *title) : fName(name), fTitle(title) { } | ||
TNamed(const TString &name, const TString &title) : fName(name), fTitle(title) { } | ||
TNamed(TString name, TString title) : fName(std::move(name)), fTitle(std::move(title)) {} |
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.
Wouldn't
TNamed(TString name, TString title) : fName(std::move(name)), fTitle(std::move(title)) {} | |
TNamed(const &TString name, const &TString title) : fName(name), fTitle(title) {} | |
TNamed(TString &&name, const TString &title) : fName(std::move(name)), fTitle(title) {} | |
TNamed(const TString &name, TString &&title) : fName(name), fTitle(std::move(title)) {} | |
TNamed(TString &&name, TString &&title) : fName(std::move(name)), fTitle(std::move(title)) {} |
be even more performant? (Albeit annoying :) )
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.
Please take a look at the discussion in #15434. Especially https://www.cppstories.com/2018/08/init-string-member/, which analyzes nearly every combination.
A const-reference is not any more performant then a plain TString
(assuming move is very cheap).
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.
Has this been tested? Either by looking at the compiler output of some "real" code or by benchmarking?
Whenever performance and compiler optimizations are involved it's always best to verify the theoretical claims since it's very hard to guess correctly.
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.
Especially cppstories.com/2018/08/init-string-member, which analyzes nearly every combination.
Actually they seems have left the case of the rvalue reference/universal forwarding as an exercise to the reader ("For now, I’d like to stop here and don’t go into details. ... " ) ;)
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.
Whenever performance and compiler optimizations are involved it's always best to verify the theoretical claims since it's very hard to guess correctly.
Agreed. Also note that TString
does have a "Small String Optimization (SSO)" which may or may not change things.
@guitargeek should I rebase or something? |
I was just closing and opening to refresh the test results. I'm baffled that there are failures in what seems like a trivial PR! |
Maybe we uncovered a problem with the TString move constructor? Any intuition, @pcanal? |
03038d2
to
fbf8dee
Compare
Rebased, so that the tests run against the latest version. Maybe it''s getting better? |
It's implementation is odd looking :(, so yeah I think this is the issue ... let me do a quick checks |
and it actually seems to be working ... so now I'll try to reproduce the failure. |
I can reproduce the failure locally. |
core/base/inc/TNamed.h
Outdated
@@ -33,9 +33,9 @@ class TNamed : public TObject { | |||
TString fTitle; //object title | |||
|
|||
public: | |||
TNamed(): fName(), fTitle() { } | |||
TNamed() = default; |
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.
TNamed() = default; | |
// The following is *not* the default implementation (i.e. do not use `= default`. | |
// Default implementation can do 'more' than expected. In this case it reset all the | |
// data member of `TNamed` and more importantly its base class `TObject`. | |
// TObject's implementation of the `IsOnHeap` bit requires the memory occupied | |
// by `TObject::fUniqueID` to *not* be reset between the execution of `TObject::operator new` | |
// and the `TObject` constructor (Finding the magic pattern there is how we can determine | |
// that the object was allocated on the heap. | |
TNamed() : fName(), fTitle() { } |
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.
I can add those comments to my PR. I am wondering, whether TNamed is the only affected class? If not, then this warning should be put in some central place instead of scattered around here? If I get this correctly, it could also affect user classes? I have opened a topic on the forum about this to discuss this outside this PR. |
That is a good question.
My guess it that it would likely affect at least all classes that derives directly from |
So this problem has been known for 5 years :( #4320 but we manage to indeed lose track of it. That PR used the following more concise pattern:
where both the It would be good to add some wording in the |
So please suggest a concise wording for this PR and I will change it. I'd probably go for TNamed() {} // your-wording then. |
For the
|
fbf8dee
to
2f9b6c8
Compare
Can we move this into another PR? (I would suggest you opening it), because it's still not clear whether the main target of the current PR is actually desired or not. And TBH, I don't have the resources to perform a proper benchmark, nor do I have good other arguments why the proposed style is better (for example more readable, more maintainable, etc). |
Passing by const-reference can mean two constructions (once on the caller, once in the ctor using the TString copy ctor). Instead passing by value and using move semantics in the ctor can reduce this to one construction on the caller and one move in the ctor. As well simplify default constructor by defaulting it. Co-Authored-By: @pcanal
2f9b6c8
to
2bafc6e
Compare
This Pull request:
Passing by const-reference can mean two constructions (once on the caller, once in the ctor using the TString copy ctor).
Instead passing by value and using move semantics in the ctor can reduce this to one construction on the caller and one move in the ctor.
Checklist:
fixes: #15434