C# (.NET) 'in StartsWith işlevinin neden neden IsPrefix'dan daha yavaş olduğunu bilen var mı?Neden işlev isprefix C# içindeki Startswith'den daha hızlıdır?
cevap
Ben çoğunlukla parçacığının geçerli kültür getirilirken düşünüyorum.
Eğer String.StartsWith
şeklini kullanabilmek için Marc'ın testini değiştirirseniz
Stopwatch watch = Stopwatch.StartNew();
CultureInfo cc = CultureInfo.CurrentCulture;
for (int i = 0; i < LOOP; i++)
{
if (s1.StartsWith(s2, false, cc)) chk++;
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds + "ms; chk: " + chk);
bunu çok daha yakın geliyor.
s1.StartsWith(s2, StringComparison.Ordinal)
kullanırsanız, CompareInfo.IsPrefix
'u kullanmadan çok daha hızlıdır (tabiki CompareInfo
'a bağlı olarak). Benim kutusunda sonuçları (değil bilimsel olarak) şunlardır:
- s1.StartsWith (s2): 6914ms
- s1.StartsWith (s2, yalancı, kültür): 5568ms
- compare.IsPrefix (s1, s2): 5200ms
- s1.StartsWith (s2, StringComparison.Ordinal): 1393ms
gerçekten sadece oldukça ucuz olan her noktada 16 bitlik tamsayılar karşılaştırarak çünkü Açıkçası bu. ,'un kültüre duyarlı kontrol yapmasını istemiyorsanız, ve performansı özellikle sizin için önemlidir, bu benim kullanacağım aşırı yüktür.
Başlatmalar IsPrefix'i dahili olarak başlatır. IsPrefix'i çağırmadan önce kültür bilgilerini atar.
İyi soru; Bir test için, alıyorum:
9156ms; chk: 50000000
6887ms; chk: 50000000
Testi kulesi:
using System;
using System.Diagnostics;
using System.Globalization;
class Program
{
static void Main()
{
string s1 = "abcdefghijklmnopqrstuvwxyz", s2 = "abcdefg";
const int LOOP = 50000000;
int chk = 0;
Stopwatch watch = Stopwatch.StartNew();
for (int i = 0; i < LOOP; i++)
{
if (s1.StartsWith(s2)) chk++;
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds + "ms; chk: " + chk);
chk = 0;
watch = Stopwatch.StartNew();
CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo;
for (int i = 0; i < LOOP; i++)
{
if (ci.IsPrefix(s1, s2)) chk++;
}
watch.Stop();
Console.WriteLine(watch.ElapsedMilliseconds + "ms; chk: " + chk);
}
}
IsPrefix kaynağını gözden geçirin. Aslında, bazı durumlarda, StartsWith'i kullanması ve birkaç tane daha işlem yapması nedeniyle StartsWith
'dan daha yavaş olacak.
[System.Security.SecuritySafeCritical] // auto-generated
public unsafe virtual bool IsPrefix(String source, String prefix, CompareOptions options)
{
if (source == null || prefix == null) {
throw new ArgumentNullException((source == null ? "source" : "prefix"),
Environment.GetResourceString("ArgumentNull_String"));
}
Contract.EndContractBlock();
int prefixLen = prefix.Length;
if (prefixLen == 0)
{
return (true);
}
if (options == CompareOptions.OrdinalIgnoreCase)
{
return source.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
}
if (options == CompareOptions.Ordinal)
{
return source.StartsWith(prefix, StringComparison.Ordinal);
}
if ((options & ValidIndexMaskOffFlags) != 0) {
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
}
// to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
// the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
return (InternalFindNLSStringEx(
m_dataHandle, m_handleOrigin, m_sortName,
GetNativeCompareFlags(options) | Win32Native.FIND_STARTSWITH | ((source.IsAscii() && prefix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
source, source.Length, 0, prefix, prefix.Length) > -1);
}