Last active
November 18, 2015 13:33
-
-
Save benaadams/079a1ded2e14bc243fd5 to your computer and use it in GitHub Desktop.
betterer
This file contains hidden or 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
| using BenchmarkDotNet; | |
| using BenchmarkDotNet.Tasks; | |
| namespace AsciiToString | |
| { | |
| [BenchmarkTask(platform: BenchmarkPlatform.X86, jitVersion: BenchmarkJitVersion.LegacyJit)] | |
| [BenchmarkTask(platform: BenchmarkPlatform.X64, jitVersion: BenchmarkJitVersion.RyuJit)] | |
| public class AsciiToString | |
| { | |
| private unsafe static int GetAsciiStringStackA(byte* input, int length) | |
| { | |
| // avoid declaring other local vars, or doing work with stackalloc | |
| // to prevent the .locals init cil flag , see: https://github.com/dotnet/coreclr/issues/1279 | |
| char* output = stackalloc char[length]; | |
| return GetAsciiStringImplementationA(output, input, length); | |
| } | |
| private unsafe static int GetAsciiStringImplementationA(char* output, byte* input, int length) | |
| { | |
| var outputStart = output; | |
| var i = 0; | |
| for (; i + 3 < length; i += 4) | |
| { | |
| *(output++) = (char)*(input++); | |
| *(output++) = (char)*(input++); | |
| *(output++) = (char)*(input++); | |
| *(output++) = (char)*(input++); | |
| } | |
| for (; i < length; i++) | |
| { | |
| *(output++) = (char)*(input++); | |
| } | |
| //return new string(outputStart, 0, length); | |
| return *outputStart; | |
| } | |
| private unsafe static int GetAsciiStringStackB(byte* input, int length) | |
| { | |
| // avoid declaring other local vars, or doing work with stackalloc | |
| // to prevent the .locals init cil flag , see: https://github.com/dotnet/coreclr/issues/1279 | |
| char* output = stackalloc char[length]; | |
| return GetAsciiStringImplementationB(output, input, length); | |
| } | |
| private unsafe static int GetAsciiStringImplementationB(char* output, byte* input, int length) | |
| { | |
| var outputStart = output; | |
| var i = 0; | |
| for (; i + 3 < length; i += 4) | |
| { | |
| *(output) = (char)*(input); | |
| *(output + 1) = (char)*(input + 1); | |
| *(output + 2) = (char)*(input + 2); | |
| *(output + 3) = (char)*(input + 3); | |
| output += 4; | |
| input += 4; | |
| } | |
| for (; i < length; i++) | |
| { | |
| *(output++) = (char)*(input++); | |
| } | |
| return *outputStart; | |
| //return new string(outputStart, 0, length); | |
| } | |
| private unsafe static int GetAsciiStringStackC(byte* input, int length) | |
| { | |
| // avoid declaring other local vars, or doing work with stackalloc | |
| // to prevent the .locals init cil flag , see: https://github.com/dotnet/coreclr/issues/1279 | |
| char* output = stackalloc char[length]; | |
| return GetAsciiStringImplementationC(output, input, length); | |
| } | |
| private unsafe static int GetAsciiStringImplementationC(char* output, byte* input, int length) | |
| { | |
| var outputStart = output; | |
| for (var i = 0; i < length; i++) | |
| { | |
| *(output++) = (char)*(input++); | |
| } | |
| return *outputStart; | |
| //return new string(outputStart, 0, length); | |
| } | |
| private static unsafe int GetAsciiStringStackD(byte[] input, int inputOffset, int length) | |
| { | |
| // avoid declaring other local vars, or doing work with stackalloc | |
| // to prevent the .locals init cil flag , see: https://github.com/dotnet/coreclr/issues/1279 | |
| char* output = stackalloc char[length]; | |
| return GetAsciiStringImplementationD(output, input, inputOffset, length); | |
| } | |
| private static unsafe int GetAsciiStringImplementationD(char* output, byte[] input, int inputOffset, int length) | |
| { | |
| for (var i = 0; i < length; i++) | |
| { | |
| output[i] = (char)input[inputOffset + i]; | |
| } | |
| return output[0]; | |
| } | |
| [Params(1, 2, 8, 64, 512, 1024, 4096, 8192, 16384)] | |
| public int MaxCounter = 0; | |
| private byte[] buffer; | |
| [Setup] | |
| public void SetupData() | |
| { | |
| buffer = new byte[MaxCounter]; | |
| } | |
| [Benchmark] | |
| [OperationsPerInvoke(4)] | |
| public unsafe int UnrolledPointer() | |
| { | |
| fixed (byte* input = buffer) | |
| { | |
| return GetAsciiStringStackA(input, MaxCounter); | |
| } | |
| } | |
| [Benchmark] | |
| [OperationsPerInvoke(4)] | |
| public unsafe int UnrolledParallelPointer() | |
| { | |
| fixed (byte* input = buffer) | |
| { | |
| return GetAsciiStringStackB(input, MaxCounter); | |
| } | |
| } | |
| [Benchmark] | |
| [OperationsPerInvoke(4)] | |
| public unsafe int SequentialPointer() | |
| { | |
| fixed (byte* input = buffer) | |
| { | |
| return GetAsciiStringStackC(input, MaxCounter); | |
| } | |
| } | |
| [Benchmark] | |
| [OperationsPerInvoke(4)] | |
| public unsafe int SequentialArray() | |
| { | |
| return GetAsciiStringStackD(buffer, 0, MaxCounter); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment