Как я могу улучшить скорость этого запроса LINQ? - PullRequest
1 голос
/ 02 февраля 2012

Я использовал long.TryParse, но переключился на регулярное выражение. В настоящее время для сообщения 123 + K требуется в общей сложности 7+ миллисекунд. 7+ миллисекунд от XElement.Parse до конца методов foreach.

Stopwatch s1 =Stopwatch.StartNew();
XElement element = XElement.Parse(xml);    

string pattern = @"\b\d+\b";
Regex r = new Regex(pattern);

IEnumerable<XElement> elementsWithPossibleCCNumbers = element
    .Descendants()
    .Where(d => d.Attributes()
        .Where(a => a.Value.Length >= 13 &&
               a.Value.Length <= 16 &&
               r.IsMatch(a.Value)).Count() == 1)
    .Select(x => x);

foreach(var x in elementsWithPossibleCCNumbers)
{
    foreach(var a in x.Attributes())
    {
        //Check if the value is a number
        if(r.IsMatch(a.Value))
        {
            //Check if value is the credit card
            if(a.Value.Length >= 13 && a.Value.Length <= 16)
            {
                a.Value = Regex.Replace(a.Value, @"\b\d{13,16}\b", match => 
                    new String('*', match.Value.Length - 4) +
                    match.Value.Substring(match.Value.Length - 4)
                );
        }
        else //If value is not a credit card, replace it with ***
                a.Value = Regex.Replace(a.Value ,@"\b\d+\b", "***");
        }
    }
}

xml = element.ToString();
s1.Stop();

XElement.Parse(xml); занимает от 2 до 3 мс.

Запрос LINQ занимает от 0,004 до 0,005 мс.

Операторы foreach занимают от 4 до 5 мс.

Ответы [ 2 ]

1 голос
/ 02 февраля 2012

Похоже, вы выполняете два поиска и замены:

  1. Замените каждый номер CC на * и последние 4 цифры
  2. Замените любой другой "CC-ish "число на том же элементе с *.

Один из подходов состоит в том, чтобы заставить XLinq работать немного сложнее для вас:

// you're not using the elements, ignore them, just get the attributes
foreach (var atr in xelt.Descendants()
                        .Where(e => e.Attributes()
                                     .Any(a => a.Value.Length >= 13
                                            && a.Value.Length <= 16))
                        .SelectMany(e => e.Attributes()))
{
    // static basicDigits = new Regex(@"\b\d+\b", RegexOptions.Compiled);
    // static ccDigits = new Regex(@"\b\d{13,16}\b", RegexOptions.Compiled);
    if (ccDigits.IsMatch(atr.Value))
    {
         atr.Value = ccDigits.Replace(
             atr.Value,
             mm => new String('*', mm.Value.Length - 4)
                   + mm.Value.Substring(mm.Value.Length - 4));
    }
    else
    {
        atr.Value = basicDigits.Replace(atr.Value, "***");
    }
}

// using 150k XML (1k nodes/5k attrs, 3 attr/node avg, avg depth 4 nodes)
// with 10% match rate:
// - 25.7 MB/s (average 100 trials)
// - 61 attributes/ms

Пример ввода XML:

<item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc">
     <item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc" real1="4444555566667777" />
     <item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc" />
     ruBTMjSesurMsP6lK2jg
 </item>

Вывод:

<item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc">
     <item f1="abc123abc" f2="helloooo ***" f3="abc123abc" real1="************7777" />
     <item f1="abc123abc" f2="helloooo 1234567" f3="abc123abc" />
     ruBTMjSesurMsP6lK2jg
</item>
0 голосов
/ 02 февраля 2012

Вы можете рассмотреть возможность предварительной компиляции вашего регулярного выражения. Статья здесь: http://en.csharp -online.net / CSharp_Regular_Expression_Recipes% E2% 80% 94Compiling_Regular_Expressions объясняет все плюсы и минусы компиляции регулярных выражений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...