Skip to content

Instantly share code, notes, and snippets.

@bbowyersmyth
Created March 1, 2016 06:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bbowyersmyth/9c13d6873b9a888f7bb7 to your computer and use it in GitHub Desktop.
Save bbowyersmyth/9c13d6873b9a888f7bb7 to your computer and use it in GitHub Desktop.
ReplaceChar
using BenchmarkDotNet;
using BenchmarkDotNet.Attributes;
using System;
namespace ConsoleApplication2
{
[Config("jobs=RyuJitX64")]
public class Replace
{
[Params(5, 12, 26, 100, 1000)]
public int length = 0;
public string _string;
[Setup]
public void Setup()
{
_string = new string('a', length);
char[] _chars = _string.ToCharArray();
// Every 10th char
for (int i = 9; i < _chars.Length; i += 10)
{
_chars[i] = '/';
}
// Last char
//_chars[length - 1] = '/';
_string = new string(_chars);
}
[Benchmark]
public string ClrReplaceBench()
{
return ClrReplace(_string, '/', 'X');
}
[Benchmark]
public string RtReplaceBench()
{
return RTReplace(_string, '/', 'X');
}
[Benchmark]
public string NewReplaceBench()
{
return NewReplace(_string, '/', 'X');
}
public string ClrReplace(string str, char oldChar, char newChar)
{
return _string.Replace(oldChar, newChar);
}
public string RTReplace(string str, char oldChar, char newChar)
{
// .net 4.6.1 does not have this if
//if (oldChar == newChar)
// return str;
unsafe
{
int firstFoundIndex = -1;
fixed (char* pChars = str)
{
for (int i = 0; i < str.Length; i++)
{
if (oldChar == pChars[i])
{
firstFoundIndex = i;
break;
}
}
}
if (-1 == firstFoundIndex)
return str;
string result = new string('\0', str.Length);
fixed (char* pChars = str)
{
fixed (char* pResult = result)
{
//Copy the characters, doing the replacement as we go.
for (int i = 0; i < firstFoundIndex; i++)
pResult[i] = pChars[i];
for (int i = firstFoundIndex; i < str.Length; i++)
pResult[i] = (pChars[i] == oldChar) ? newChar : pChars[i];
}
}
return result;
}
}
public string NewReplace(string str, char oldChar, char newChar)
{
// .net 4.6.1 does not have this if
//if (oldChar == newChar)
// return str;
unsafe
{
//int currentIndex = -1;
int remainingLength = str.Length;
char* pSrc;
char* pDst;
fixed (char* pChars = str)
{
pSrc = pChars;
while (remainingLength > 0)
{
if (*pSrc == oldChar)
{
break;
}
remainingLength--;
pSrc++;
}
}
if (remainingLength == 0)
return str;
string result = new string('\0', str.Length);
fixed (char* pChars = str)
{
fixed (char* pResult = result)
{
//Copy the characters, doing the replacement as we go.
pSrc = pChars;
pDst = pResult;
int copyLength = str.Length;
while (copyLength > remainingLength)
{
*(int*)pDst = *(int*)pSrc;
copyLength -= 2;
pSrc+=2;
pDst+=2;
}
pSrc = pChars + (str.Length - remainingLength);
pDst = pResult + (str.Length - remainingLength);
do
{
char currentChar = *pSrc;
if (currentChar == oldChar)
currentChar = newChar;
*pDst = currentChar;
remainingLength--;
pSrc++;
pDst++;
} while (remainingLength > 0);
}
}
return result;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment