Skip to content
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

[c++] Use memcpy to type pun; fix alias violations #375

Closed
wants to merge 1 commit into from

Conversation

chwarr
Copy link
Member

@chwarr chwarr commented Mar 22, 2017

We now use memcpy to pun from one type to another, avoiding aliasing
violations as well as alignment errors. x86-like chips never failed due
to the alignment errors, but others, like some ARM chips, did. This
should also fix emscripten cross-compilation.

Fixes #305

value = *reinterpret_cast<const T*>(_blob.content() + _pointer);

const void* const src = _blob.content() + _pointer;
std::memcpy(&value, src, sizeof(T));
Copy link
Member Author

@chwarr chwarr Mar 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: see whether on x86 there's any performance regression due to this change in reading. If there is, add a guard and do the unaligned access like as before, like in output_buffer.

Copy link
Member Author

@chwarr chwarr Mar 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did some testing, and the reinterpret_cast code path is faster for amd64 MSVC, so I've added it back in the most recent push.

@@ -19,18 +21,19 @@ struct VariableUnsignedUnchecked
{
BOOST_STATIC_ASSERT(N < 10);

static uint32_t Write(uint8_t* p, T value)
static uint32_t Write(char* p, T value)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was no measurable performance implication due to these changes when I tested.

// which results in call to memcpy() and additional memory access.
// The direct copy of the value (which is likely on register already)
// is faster.
// x86/x64 performance tweak: for small types don't go into generic
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I re-validated that this tweak still results in better performance--at least with MSVC.

@@ -298,7 +314,7 @@ class OutputMemoryStream
{
if (sizeof(T) * 8 / 7 + _rangeSize + _rangeOffset < _bufferSize)
{
uint8_t* ptr = reinterpret_cast<uint8_t*>(_rangePtr + _rangeSize);
char* ptr = _rangePtr + _rangeSize;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: can be const

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pointer can be const, but the thing it points to cannot. Not worth the potential confusion. Leaving as-is.

@chwarr
Copy link
Member Author

chwarr commented Mar 22, 2017

@glenfe, if you have time, I would appreciate if you could take a look at these changes. You're knowledge of the C++ standards is far better than mine. Thanks in advance.

@glenfe
Copy link
Contributor

glenfe commented Mar 22, 2017

Looks fine to me.

When reviewing the changes (but unrelated to your change) I noticed some things with the use of allocators: I'll create a proper Issue about it tomorrow.

We now use memcpy to pun from one type to another, avoiding aliasing
violations as well as alignment errors. x86-like chips never failed due
to the alignment errors, but others, like some ARM chips, did. This
should also fix emscripten cross-compilation.

Fixes microsoft#305
@chwarr chwarr force-pushed the chwarr/cpp-type-puns branch from 1ba29cd to 4be8d35 Compare March 23, 2017 23:01
@chwarr
Copy link
Member Author

chwarr commented Mar 24, 2017

Official AppVeyor builds are completely backed up due to some work @tstein is doing to improve the coverage we have on Travis for versions of Boost. (He's going to remove appveyor.yml in a subsequent change so that this doesn't keep happening.)

This change passed on my AppVeyor config, with the usual timeout in the VC14 C++ build during tests. I ran all of these tests on my local machine.

Going to merge.

@chwarr chwarr closed this in 04ad85f Mar 24, 2017
@chwarr chwarr deleted the chwarr/cpp-type-puns branch March 28, 2017 23:31
fuzhouch pushed a commit to fuzhouch/bond that referenced this pull request Apr 9, 2017
We now use memcpy to pun from one type to another, avoiding aliasing
violations as well as alignment errors. x86-like chips never failed due
to the alignment errors, but others, like some ARM chips, did. This
should also fix emscripten cross-compilation.

Fixes microsoft#305
Closes microsoft#375
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Alignment issues in serializers
3 participants