Dlaczego długość wejścia w wyrażeniu regularnym nie ma wpływu na wydajność i jak to jest możliwe?Dlaczego regex nie dba o długość ciągu znaków
Wygenerowany ciąg jest następujący: 128 losowych znaków. następnie dwie liczby w nawiasach. i to się powtarza wiele razy.
128 radnom characters....(-2435346|45436) 128 radnom characters....(-32525562|-325346)
Wyliczenie pobiera wszystkie liczby wewnątrz nawiasów. tutaj jest wzór.
\(([-+]?\d+\|[-+]?\d+)\)
Więc mecze będzie jak
-2435346|45436
-32525562|-325346
etc...
Oto kod, który ma punkt odniesienia. Zaczynam stop stop po wygenerowaniu wejścia, ponieważ chcę tylko ocenić czas dopasowania.
Random rand = new Random();
Func<string> getRandString = // generates 128 random characters.
() => Enumerable.Range(0, 128).Select(x => (char) rand.Next()).Aggregate("", (a, b) => a + b);
Func<int> getRandInteger =() => rand.Next(); // generates random number.
string format = "{0}({1}|{2})";
// Generate the big string.
StringBuilder bigstr = new StringBuilder();
for (int i = 0; i < 100; i++) // repeat 100 times.
{
bigstr.Append(string.Format(format, getRandString(), getRandInteger(), getRandInteger()));
}
string input = bigstr.ToString();
Stopwatch stopwatch = Stopwatch.StartNew();
var matches = Regex.Matches(input, @"\(([-+]?\d+\|[-+]?\d+)\)");
stopwatch.Stop();
Console.WriteLine("Time Elapsed :\t{0}\nInputLength :\t{1}\nMatches Count :\t{2}", stopwatch.Elapsed, input.Length, matches.Count);
Jest to wyjście w mojej konsoli, jeśli powtarzam pętli 10
razy.
Time Elapsed : 00:00:00.0004132
InputLength : 1500
Matches Count : 10
Jeśli powtórzę pętlę 1000
razy.
Time Elapsed : 00:00:00.0004373 // seriously?
InputLength : 149937
Matches Count : 1000
Jeśli powtórzę pętlę 1000000
razy.
Time Elapsed : 00:00:00.0004900 // wtf?
InputLength : 149964452
Matches Count : 1000000
ekranu, jeśli nie wierzą
Czy to jakiś rodzaj oceny leniwy? jeśli tak, to w jaki sposób może pokazywać liczbę dopasowań? jak to zrobiłem podczas debuggera i mogłem zobaczyć mecze.
Czy jest coś szczególnego w moim schemacie regex, który czyni go szybkim? ale jak długość ciągu nie wpływa na wydajność? Nie mogę zrozumieć.
Nie ma w tym nic szczególnego. Twój silnik wyrażeń przetrzyma ciąg znaków i zapisze wszystkie stany pasujące do Twojego wyrażenia regularnego, a ty będziesz mieć benchmark na 1000-razowym dłuższym łańcuchu, który nie jest wielkim problemem dla maszyn adi. znacznie większe struny.A może twój benchmarikon nie jest sprawiedliwy. – Kasramvd
Możesz być zainteresowany [tą odpowiedzią] (http://stackoverflow.com/a/32618592/3764814), jeśli chcesz zobaczyć szczegóły dotyczące algorytmu wyszukiwania ciągów używanego przez silnik regex .NET. –
Prawidłowe testy porównawcze: https://andreyakinshin.gitbooks.io/performancebookdotnet/content/science/microbenchmarking.html –