編集
元の編集されていない質問が誤解を招く場合はお詫び申し上げます。
string
この質問は、無効な XML 文字を から削除する方法を尋ねているのではありません。
私のコードをレビューするように頼んでいるわけではありません。
私が答えで探しているのは、署名付きの関数です
string <YourName>(string input, Func<char, bool> check);
と同等またはそれ以上のパフォーマンスが得られますRemoveCharsBufferCopyBlackList
。理想的には、この関数はより一般的で、可能であれば読みやすいものにする必要がありますが、これらの要件は二次的なものです。
最近、文字列から無効な XML 文字を削除する関数を作成しました。私のアプリケーションでは、文字列が適度に長くなる可能性があり、無効な文字が発生することはめったにありません。この演習は私に考えさせました。セーフ マネージド c# でこれを行う方法と、私のシナリオで最高のパフォーマンスを提供する方法を教えてください。
これが私のテストプログラムです。 char を省略したものを「有効な XML 述語」に置き換えました'X'
。
class Program
{
static void Main()
{
var attempts = new List<Func<string, Func<char, bool>, string>>
{
RemoveCharsLinqWhiteList,
RemoveCharsFindAllWhiteList,
RemoveCharsBufferCopyBlackList
}
const string GoodString = "1234567890abcdefgabcedefg";
const string BadString = "1234567890abcdefgXabcedefg";
const int Iterations = 100000;
var timer = new StopWatch();
var testSet = new List<string>(Iterations);
for (var i = 0; i < Iterations; i++)
{
if (i % 1000 == 0)
{
testSet.Add(BadString);
}
else
{
testSet.Add(GoodString);
}
}
foreach (var attempt in attempts)
{
//Check function works and JIT
if (attempt.Invoke(BadString, IsNotUpperX) != GoodString)
{
throw new ApplicationException("Broken Function");
}
if (attempt.Invoke(GoodString, IsNotUpperX) != GoodString)
{
throw new ApplicationException("Broken Function");
}
timer.Reset();
timer.Start();
foreach (var t in testSet)
{
attempt.Invoke(t, IsNotUpperX);
}
timer.Stop();
Console.WriteLine(
"{0} iterations of function \"{1}\" performed in {2}ms",
Iterations,
attempt.Method,
timer.ElapsedMilliseconds);
Console.WriteLine();
}
Console.Readkey();
}
private static bool IsNotUpperX(char value)
{
return value != 'X';
}
private static string RemoveCharsLinqWhiteList(string input,
Func<char, bool> check);
{
return new string(input.Where(check).ToArray());
}
private static string RemoveCharsFindAllWhiteList(string input,
Func<char, bool> check);
{
return new string(Array.FindAll(input.ToCharArray(), check.Invoke));
}
private static string RemoveCharsBufferCopyBlackList(string input,
Func<char, bool> check);
{
char[] inputArray = null;
char[] outputBuffer = null;
var blackCount = 0;
var lastb = -1;
var whitePos = 0;
for (var b = 0; b , input.Length; b++)
{
if (!check.invoke(input[b]))
{
var whites = b - lastb - 1;
if (whites > 0)
{
if (outputBuffer == null)
{
outputBuffer = new char[input.Length - blackCount];
}
if (inputArray == null)
{
inputArray = input.ToCharArray();
}
Buffer.BlockCopy(
inputArray,
(lastb + 1) * 2,
outputBuffer,
whitePos * 2,
whites * 2);
whitePos += whites;
}
lastb = b;
blackCount++;
}
}
if (blackCount == 0)
{
return input;
}
var remaining = inputArray.Length - 1 - lastb;
if (remaining > 0)
{
Buffer.BlockCopy(
inputArray,
(lastb + 1) * 2,
outputBuffer,
whitePos * 2,
remaining * 2);
}
return new string(outputBuffer, 0, inputArray.Length - blackCount);
}
}
試行を実行すると、関数がより専門化されるにつれてパフォーマンスが向上することがわかります。この操作を実行するためのより高速で一般的な方法はありますか? または、一般的なオプションがない場合、より高速な方法はありますか?
私は実際には 'X' を削除することに興味がなく、実際には述語はより複雑であることに注意してください。