-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
Modified Vector STL bind initialization from a buffer type with optimization for simple arrays #2298
Merged
Merged
Modified Vector STL bind initialization from a buffer type with optimization for simple arrays #2298
Changes from 1 commit
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
ddc4704
Modified Vector STL bind initialization from a buffer type with optim…
1fcc435
Add subtests to demonstrate processing Python buffer protocol objects…
ac6ea0f
Fixed memoryview step test to only run on Python 3+
0dcf899
Modified Vector constructor from buffer to return by value for readab…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
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.
Out of curiosity: can we get rid of
std::unqiue_ptr
? I'm not aware of any performance penalties of return-by-value alternative which looks much cleaner.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 don't see any issues with doing that, performance looks the same to me.
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.
It definitely looks cleaner, but there's a possibility that only one of the two branches will have return value optimization applied. In theory, it should be possible to apply RVO to both branches, but I don't think compilers do that (yet). Can we check what are the compilers actually doing?
I mean, we're getting a pretty nice performance improvement, but maybe copying 6'000'000 objects would negate the performance improvements.
Reading the source some more, the first branch would return a temporary and RVO there is guaranteed. Considering that the size of the vector "blueprints" is constant (3 pointers), it might work better than I expect.
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.
Even if no RVO is involved the result should be moved with no performance hit, right?
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.
You're right. It will definitely be possible to move the vector, instead of copying.
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.
make_unique
is just syntax sugar, no? In comparison,make_shared
can IIRC avoid a memory allocation compared to the naive initialization.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 think it is, yes. But it's shorter (doesn't repeat the type) and makes things feel more atomic (whereas
unique_ptr<T>(new T())
allows you to be tempted to split up thenew
and the construction ofunique_ptr
, which could result in leaks on exceptions, etc).But it's C++14, so nevermind all that :-D
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.
Since I was the one bringing up RVO and whether it works...
In other words, after populating the vector, we move 3 words, from the top of the stack into
R13
and return a little later. This is what a move looks like. At O3 it will be further optimized to 128bit move + 64bit move, instead of 3 x 64bit moves.You guessed it. RVO works here.
This is the exact same thing as GCC, just with different registers. Except that I couldn't get MSVC to use XMM0 and perform a 128bit move.
The branch with the temporary gets optimized to a
memcpy
and RVO is used. The assembly is just beautiful in this case.@YannickJadoul
True, but we're talking about a
std::vector
-like container. You're not moving theT
s. You're moving the container "blueprints". Is there a reasonable "vector-like" container with expensive move constructor?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.
Whooooa, great investigation, @bstaletic! :-D
Probably not; I'm just thinking of some custom thing, but then it might be the user's own problem if they can't implement a decent move constructor.
On the other hand, I'm wondering that if it doesn't matter, why not just keep it like this?
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.
Because readability and maintainability. It's easier to reason about the code without needless indirections.