myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Basistechnologien und allgemeine .NET-Klassen » Performance von Regex
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Performance von Regex

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin


herbivore ist offline

Performance von Regex

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Community, hallo Pulpapex,

du hattest schon öfter geschrieben, dass man RegexOptions.Compiled benutzen soll, und dass das dynamische Erzeugen von Pattern teuer ist. Mich hat mal interessiert, was wie teuer was ist und habe dem folgenden Programm gemessen.

C#-Code:
//#define SW_ONEPATTERN
//#define SW_COMPILED
using System;
using System.Text.RegularExpressions;

abstract class App
{
   public static void Main (string [] astrArg)
   {
      DateTime dt;

      int iOk = 0;
      int iNichtOk = 0;
      int i = 0;
      int iCount;

      dt = DateTime.Now;

      #if SW_ONEPATTERN
      #if SW_COMPILED
      Regex re = new Regex ("hu.*hu" + i, RegexOptions.Compiled);
      iCount = 1000000;
      #else
      Regex re = new Regex ("hu.*hu" + i);
      iCount = 1000000;
      #endif
      #else
      #if SW_COMPILED
      iCount = 1000;
      #else
      iCount = 100000;
      #endif
      #endif
      for (i = 0; i < iCount; ++i) {
         #if !SW_ONEPATTERN
         #if SW_COMPILED
         Regex re = new Regex ("hu.*hu" + i, RegexOptions.Compiled);
         #else
         Regex re = new Regex ("hu.*hu" + i);
         #endif
         #endif
         if (re.IsMatch ("huhuhu1000")) {
            ++iOk;
         } else {
            ++iNichtOk;
         }
      }
      Console.WriteLine (DateTime.Now - dt);
      Console.WriteLine ("für " + iCount + " Schleifendurchläufe");

      #if SW_ONEPATTERN
      Console.WriteLine (" SW_ONEPATTERN");
      #else
      Console.WriteLine ("!SW_ONEPATTERN");
      #endif
      #if SW_COMPILED
      Console.WriteLine (" SW_COMPILED");
      #else
      Console.WriteLine ("!SW_COMPILED");
      #endif

      // Console.WriteLine (iOk);
      // Console.WriteLine (iNichtOk);
   }
}

Ergebnisse:

SW_ONEPATTERN
SW_COMPILED
1Mio = ca. 1.4s

SW_ONEPATTERN
!SW_COMPILED
1Mio = ca. 2.4s

!SW_ONEPATTERN
!SW_COMPILED
100k = ca. 2.4s

!SW_ONEPATTERN
SW_COMPILED
1000 = ca. 2.5s

Wenn ich die Zahlen richtig interpretiere und natürlich mit der Einschränkung, dass sie erstmal nur für die verwendeten Pattern und Strings gelten, ist ein Match mit einem nicht compilierten Pattern rund doppelt so teuer, wie mit einem compilierten Pattern. Das Erzeugen eines nicht compilierten Patterns ist ca. 10 mal teuer als ein Match und das Erzeugen eines compilierten Pattern ist nochmal 100 mal teuer als das Erzeugen eines nicht compilierten Patterns.

Wenn man also nur wenige Matches (<50) macht, scheint es mir also gerade nicht sinnvoll RegexOptions.Compiled zu benutzen.

herbivore

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von herbivore am 29.10.2005 09:29.

27.10.2005 21:42 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
norman_timo norman_timo ist männlich
myCSharp.de-Mitglied

avatar-1775.jpeg


Dabei seit: 13.07.2004
Beiträge: 4.506
Entwicklungsumgebung: .NET 2.0/3.5 und VS2005/VS2008
Herkunft: Wald-Michelbach (Odw)


norman_timo ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Herbivore!

Verkaufst Du das an eine UNI? :-)

Nein, Scherz beiseite, solch ein Testverfahren ergibt doch eindeutige Rückschlüsse, daher coole Aktion.

Ciao
Norman-Timo
28.10.2005 09:26 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
.unreal .unreal ist männlich
myCSharp.de-Mitglied

avatar-1903.gif


Dabei seit: 26.11.2004
Beiträge: 563
Entwicklungsumgebung: VS 2005
Herkunft: Nähe Zürich


.unreal ist offline Füge .unreal Deiner Kontaktliste hinzu MSN-Passport-Profil von .unreal anzeigen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

kann ich nur unterstreichen! ich hab mich schon oft gefragt, was schneller ist smile

sauber sache!
28.10.2005 11:10 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
svenson svenson ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.04.2005
Beiträge: 8.746
Entwicklungsumgebung: Visual Studio .NET 2003
Herkunft: Berlin


svenson ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Es sei noch zu ergänzen, dass die statische Variante, gegenüber der nicht-compilierten Objekt-Variante nochmal erheblich schneller ist. Die Ursache ist, dass die Objekt-Erzeugung oft teurer ist, als die Auswertung des Ausdrucks selbst. Ist natürlich abhängig vom Ausdruck sowie der Größe des Suchfeldes.

Vielleicht kann Herbi das ja nochmal in den Test einbauen....

Im Prinzip macht es wenig Sinn, die Objekt-Variante ohne Compilierung zu nutzen... so zumindest mein Eindruck.
28.10.2005 11:12 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin

Themenstarter Thema begonnen von herbivore

herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo svenson,

ich verstehe nicht genau, welche neue Variante zu meinst. Was meinst du mit statisch? Sorry, kannst du bitte den gewünschten Testfall nochmal mit anderen Worten beschreiben?

herbivore
28.10.2005 13:35 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
cdr cdr ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.08.2003
Beiträge: 980
Herkunft: Zürich


cdr ist offline MSN-Passport-Profil von cdr anzeigen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Statisch tönt verdächtig nach

C#-Code:
public static bool Regex.IsMatch(string input, string pattern);
28.10.2005 23:16 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin

Themenstarter Thema begonnen von herbivore

herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo cdr,

hm, für mich ist das das Gegenteil von statisch, weil ich ja gerade bei jedem Aufruf bel. Parameter mitgeben kann. Aber an sich ist es natürlich eine interessante Frage wie

C#-Code:
if (Regex.IsMatch ("huhuhu1000", "hu.*hu" + i))

gegenüber

C#-Code:
Regex re = new Regex ("hu.*hu" + i);
if (re.IsMatch ("huhuhu1000"))

abschneidet. Es kommt jedoch erwartungsgemäß ziemlich aufs gleiche heraus (Abweichung im Rahmen der Messungenauigkeit).

herbivore

PS: Ich habe den Originalbeitrag korrigiert. Das Erzeugen eines nicht compilierten Patterns ist entsprechend der Messergebnisse natürlich nur ca. 10 mal (und nicht 100 mal) teuer als ein Match.
29.10.2005 09:29 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
cdr cdr ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.08.2003
Beiträge: 980
Herkunft: Zürich


cdr ist offline MSN-Passport-Profil von cdr anzeigen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ja, ich würde auch etwas das gleiche erwarten, wenn man bedenkt dass die statische Methode ja auch einfach eine Instanz erstellt ...

C#-Code:
public static bool Regex.IsMatch(string input, string pattern)
{
      return new Regex(pattern, RegexOptions.None, true).IsMatch(input);
}
29.10.2005 12:31 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr.
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin

Themenstarter Thema begonnen von herbivore

herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo zusammen,

anzumerken ist noch, dass es eine Methode Regex.CompileToAssembly gibt, mit der man die Compilierung des Pattern von Zeitpunkt der Programmausführung auf den Zeitpunkt der Compilierung des Programms verlagern kann. Damit hat man zu Laufzeit des Programms den Vorteil von Faktor 10 beim Match ohne den Nachteil von Faktor 100 beim Compilieren des Pattern.

herbivore
12.07.2007 08:29 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LonelyPixel
myCSharp.de-Mitglied

Dabei seit: 21.03.2007
Beiträge: 333
Entwicklungsumgebung: VS 2010
Herkunft: Erlangen


LonelyPixel ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Von dem CompileToAssembly steht in meiner MSDN aber nichts. Kannst du mir verraten, wo du das her hast?

Im übrigen bin ich nach der Beschreibung von Compiled bereits davon ausgegangen, dass der Ausdruck fest ins Assembly einkompiliert wird, daher war ich über den enormen einmaligen Aufwand zur Laufzeit, der oben beschrieben wurde, jetzt doch sehr überrascht. Allerdings verstehe ich deinen Beispielcode auch nicht.

--- edit
Argh, okay, ich sollte nicht so schnell lesen. Du meintest natürlich nicht RegexOptions. Aber auch diese Methode schaut verwirrend aus. Bedeutet das, dass ich zur Laufzeit des Programms einen Regex in eine zusätzliche Datei kompilieren lassen kann, die dann wie genau verwendet wird? Gibt es denn keine Methode, einen Regex fest in das Programm einzukompilieren? Ich mein das jetzt so wie z.B. in den Programmiersprachen der 70er Jahre SQL statisch kompiliert wurde, um die Performance zu steigern.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von LonelyPixel am 12.07.2007 12:43.

12.07.2007 12:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin

Themenstarter Thema begonnen von herbivore

herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo LonelyPixel,

die Methode steht ganz normal in der Bitte schau in die SDK-/MSDN-Doku Doku:  Regex.CompileToAssembly-Methode. Keine Ahnung, warum du sie nicht gefunden hast.

Zitat:
Im übrigen bin ich nach der Beschreibung von Compiled bereits davon ausgegangen, dass der Ausdruck fest ins Assembly einkompiliert wird

Nein, das ist nicht der Fall. Mit RegexOptions.Compiled wird der Pattern dynamisch zur Laufzeit des Programm compiliert.

Woher sollte der arme C#-Compiler auch wissen, dass er was spezielles machen sollte, nur weil er auf einen bestimmten Enum-Wert stößt. Er setzt den RegexOptions.Compiled einfach in seinen numerischen Wert um und damit hat es sich für ihn erledigt. Alles weiter passiert erst, wenn der Konstruktor mit diesem Wert aufgerufen wird, also zur Laufzeit des Programms.

herbivore
12.07.2007 12:49 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
herbivore
myCSharp.de-Poweruser/ Experte

avatar-2627.gif


Dabei seit: 11.01.2005
Beiträge: 49.464
Entwicklungsumgebung: csc/nmake (nothing is faster)
Herkunft: Berlin

Themenstarter Thema begonnen von herbivore

herbivore ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo LonelyPixel,

Zitat:
Bedeutet das, dass ich zur Laufzeit des Programms einen Regex in eine zusätzliche Datei kompilieren lassen kann, die dann wie genau verwendet wird?

nein, man schreibt natürlich sinnvollerweise ein kleines Programm, dass zum Build-Zeitpunkt ausgeführt wird und mit Regex.CompileToAssembly die Assembly erstellt, die dann gleich - immer noch zum Build-Zeitpunkt - vom eigentlichen Programm referenziert wird.

Zitat:
Gibt es denn keine Methode, einen Regex fest in das Programm einzukompilieren?

Doch, eben Regex.CompileToAssembly.

Zitat:
Ich mein das jetzt so wie z.B. in den Programmiersprachen der 70er Jahre SQL statisch kompiliert wurde, um die Performance zu steigern.

Nein, in dieser Art wie bei embeded SQL läuft es nicht, sondern so, wie ich gerade beschrieben habe.

herbivore
12.07.2007 12:54 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr.
cdr cdr ist männlich
myCSharp.de-Mitglied

Dabei seit: 22.08.2003
Beiträge: 980
Herkunft: Zürich


cdr ist offline MSN-Passport-Profil von cdr anzeigen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Falls diesen Thread wieder mal jemand findet, ein interessanter Artikel über die Innereien der .Net regular expressions (auch zum Thema Compilation):  How .NET Regular Expressions Really Work
01.04.2009 01:02 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Beauty
myCSharp.de-Mitglied

avatar-2333.jpg


Dabei seit: 31.05.2007
Beiträge: 79
Entwicklungsumgebung: Visual C# 2008
Herkunft: Thüringen


Beauty ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Danke herbivore für Deinen Test und die Auswertung hier im Forum!


Danke auch an cdr - der Link ist interessant.
Schade finde ich allerdings, daß bei den .NET RegEx keine Rekursionen möglich sind. (So las ich es zumindest hier im Forum.)
Interessant sind übrigens die Fähigkeiten der Regex von Perl 6. Da kann man auch richtig komplexe Ausdrücke aus einzelnen Teilausdrücken zusammenbauen (Vererbungs-Prinzip?). Wenn ich richtig verstanden habe, prüft sich der Interpreter sogar selbst (durch Regex), ob die Syntax seines eigenen Quellcodes richtig ist. Klingt irgendwie leicht verrückt, paßt aber zur Perl-Philosophie *g* Dies nur am Rande.
01.04.2009 03:45 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 14 Jahre.
Der letzte Beitrag ist älter als 10 Jahre.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 12.11.2019 06:48