Skip to content

Instantly share code, notes, and snippets.

@bbowyersmyth
Last active May 30, 2016 01:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbowyersmyth/791ff071a10ef901ed7a to your computer and use it in GitHub Desktop.
Save bbowyersmyth/791ff071a10ef901ed7a to your computer and use it in GitHub Desktop.
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