Decrease writes to local variables in Buffer.MemoryCopy (dotnet/coreclr#6627)
authorJames Ko <jamesqko@gmail.com>
Sat, 6 Aug 2016 02:06:59 +0000 (22:06 -0400)
committerJan Kotas <jkotas@microsoft.com>
Sat, 6 Aug 2016 02:06:59 +0000 (19:06 -0700)
commitfc846508103b5361ebde9a694c2b898f8e716b98
tree9214183077fb1d032485b7df73f733fded993503
parent5bc7eba53cdcc09e379951bc5ab593b12e9bb843
Decrease writes to local variables in Buffer.MemoryCopy (dotnet/coreclr#6627)

In `Buffer.MemoryCopy` currently we are making 4 writes every time we copy some data; 1 to update `*dest`, 1 to update `dest`, 1 to update `src` and 1 to update `len`. I've decreased it to 2; one to update a new local variable `i`, which keeps track of how many bytes we are into the buffer. All writes are now made using

```cs
*(dest + i + x) = *(src + i + x)
```

which has no additional overhead since they're converted to using memory addressing operands by the jit.

Another change I made was to add a few extra cases for the switch-case at the beginning that does copying for small sizes without any branches. It now covers sizes 0-22. This is beneficial to the main codepath, since we can convert the unrolled loop to a `do..while` loop and save an extra branch at the beginning. (max 7 bytes for alignment, 16 for 1 iteration of the loop, so the min bytes we can copy without checking whether we should stop is 23.) This adds

This PR increases the performance of `MemoryCopy` by 10-20% for most buffer sizes on x86; you can see the performance test/results (and the generated assembly for each version) [here](https://gist.github.com/jamesqo/337852c8ce09205a8289ce1f1b9b5382). (Note that this codepath is also used by `wstrcpy` at the moment, so this directly affects many common String operations.)

Commit migrated from https://github.com/dotnet/coreclr/commit/32fe06348631c9e146832e5afac2ce97bb2df43e
src/coreclr/src/mscorlib/src/System/Buffer.cs