Last active
May 30, 2016 01:31
-
-
Save bbowyersmyth/791ff071a10ef901ed7a to your computer and use it in GitHub Desktop.
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
using BenchmarkDotNet.Attributes; | |
using System; | |
namespace ConsoleApplication2 | |
{ | |
[Config("jobs=RyuJitX64")] | |
public class IndexOf | |
{ | |
// Not found | |
[Params(1, 12, 50, 100, 200, 500)] | |
public int length = 0; | |
// Different at pos n | |
//[Params(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14)] | |
//public int offset = 0; | |
//public int length = 15; | |
public string _string; | |
[Setup] | |
public void Setup() | |
{ | |
// Not found | |
_string = new string('a', length); | |
// Different at pos n | |
//_string = new string('a', 15); | |
//var chars = _string.ToCharArray(); | |
//chars[offset] = 'X'; | |
//_string = new string(chars); | |
} | |
[Benchmark] | |
public int ClrIndexOf() | |
{ | |
return _string.IndexOf('X', 0, length); | |
} | |
[Benchmark] | |
public int RtIndexOf() | |
{ | |
return RtIndexOf('X', 0, length); | |
} | |
[Benchmark] | |
public int NewIndexOf() | |
{ | |
return NewIndexOf('X', 0, length); | |
} | |
[Benchmark] | |
public int NewIndexOfUnroll() | |
{ | |
return NewIndexOfUnroll('X', 0, length); | |
} | |
[Benchmark] | |
public int ClrLastIndexOf() | |
{ | |
return _string.LastIndexOf('X', length - 1, length); | |
} | |
[Benchmark] | |
public int NewLastIndexOf() | |
{ | |
return NewLastIndexOf('X', length - 1, length); | |
} | |
public unsafe int RtIndexOf(char value, int startIndex, int count) | |
{ | |
if (startIndex < 0 || startIndex > _string.Length) | |
throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_Index"); | |
if (count < 0 || count > _string.Length - startIndex) | |
throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_Count"); | |
fixed (char* pChars = _string) | |
{ | |
char* pCh = pChars + startIndex; | |
for (int i = 0; i < count; i++) | |
{ | |
if (*pCh == value) | |
return i + startIndex; | |
pCh++; | |
} | |
} | |
return -1; | |
} | |
public unsafe int NewIndexOf(char value, int startIndex, int count) | |
{ | |
if (startIndex < 0 || startIndex > _string.Length) | |
throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_Index"); | |
if (count < 0 || count > _string.Length - startIndex) | |
throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_Count"); | |
fixed (char* pChars = _string) | |
{ | |
char* pCh = pChars + startIndex; | |
char* pEnd = pCh + count; | |
while (pCh < pEnd) | |
{ | |
if (*pCh == value) | |
goto ReturnIndex; | |
pCh++; | |
} | |
return -1; | |
ReturnIndex: | |
return (int)(pCh - pChars); | |
} | |
} | |
public unsafe int NewIndexOfUnroll(char value, int startIndex, int count) | |
{ | |
if (startIndex < 0 || startIndex > _string.Length) | |
throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_Index"); | |
if (count < 0 || count > _string.Length - startIndex) | |
throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_Count"); | |
fixed (char* pChars = _string) | |
{ | |
char* pCh = pChars + startIndex; | |
int offset = 0; | |
while (count >= 4) | |
{ | |
if (*pCh == value) goto ReturnIndex; | |
if (*(pCh + 1) == value) goto ReturnIndex1; | |
if (*(pCh + 2) == value) goto ReturnIndex2; | |
if (*(pCh + 3) == value) goto ReturnIndex3; | |
count -= 4; | |
pCh += 4; | |
} | |
while (count > 0) | |
{ | |
if (*pCh == value) goto ReturnIndex; | |
count--; | |
pCh++; | |
} | |
return -1; | |
ReturnIndex3: | |
offset = 3; | |
goto ReturnIndex; | |
ReturnIndex2: | |
offset = 2; | |
goto ReturnIndex; | |
ReturnIndex1: | |
offset = 1; | |
ReturnIndex: | |
return (int)(pCh - pChars) + offset; | |
} | |
} | |
public unsafe int RTLastIndexOf(char value, int startIndex, int count) | |
{ | |
if (_string.Length == 0) | |
return -1; | |
if (startIndex < 0 || startIndex >= _string.Length) | |
throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_Index"); | |
if (count < 0 || count - 1 > startIndex) | |
throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_Count"); | |
fixed (char* pChars = _string) | |
{ | |
char* pCh = pChars + startIndex; | |
//We search [startIndex..EndIndex] | |
for (int i = 0; i < count; i++) | |
{ | |
if (*pCh == value) | |
return startIndex - i; | |
pCh--; | |
} | |
} | |
return -1; | |
} | |
public unsafe int NewLastIndexOf(char value, int startIndex, int count) | |
{ | |
if (_string.Length == 0) | |
return -1; | |
if (startIndex < 0 || startIndex >= _string.Length) | |
throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_Index"); | |
if (count < 0 || count - 1 > startIndex) | |
throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_Count"); | |
fixed (char* pChars = _string) | |
{ | |
char* pCh = pChars + startIndex; | |
char* pEnd = pCh - count; | |
//We search [startIndex..EndIndex] | |
while (pCh > pEnd) | |
{ | |
if (*pCh == value) | |
goto ReturnIndex; | |
pCh--; | |
} | |
return -1; | |
ReturnIndex: | |
return (int)(pCh - pChars); | |
} | |
} | |
public unsafe int NewLastIndexOfUnroll(char value, int startIndex, int count) | |
{ | |
if (_string.Length == 0) | |
return -1; | |
if (startIndex < 0 || startIndex >= _string.Length) | |
throw new ArgumentOutOfRangeException("startIndex", "ArgumentOutOfRange_Index"); | |
if (count < 0 || count - 1 > startIndex) | |
throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_Count"); | |
fixed (char* pChars = _string) | |
{ | |
char* pCh = pChars + startIndex; | |
int offset = 0; | |
while (count >= 4) | |
{ | |
if (*pCh == value) goto ReturnIndex; | |
if (*(pCh - 1) == value) goto ReturnIndex1; | |
if (*(pCh - 2) == value) goto ReturnIndex2; | |
if (*(pCh - 3) == value) goto ReturnIndex3; | |
count -= 4; | |
pCh -= 4; | |
} | |
while (count > 0) | |
{ | |
if (*pCh == value) goto ReturnIndex; | |
count--; | |
pCh--; | |
} | |
return -1; | |
ReturnIndex3: | |
offset = 3; | |
goto ReturnIndex; | |
ReturnIndex2: | |
offset = 2; | |
goto ReturnIndex; | |
ReturnIndex1: | |
offset = 1; | |
ReturnIndex: | |
return (int)(pCh - pChars) - offset; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment