2009-09-29 8 views
5

J'ai une situation où mes expressions régulières compilent extrêmement lentement sur Windows Server 2008. J'ai écrit une petite application console pour mettre en évidence ce problème. L'application génère sa propre entrée et construit un Regex à partir de mots dans un fichier XML. J'ai construit une version de cette application et l'ai exécutée à la fois sur mon ordinateur portable personnel (exécutant XP) et sur le serveur Windows 2008. L'expression régulière a pris 0,21 secondes pour compiler sur mon ordinateur portable, mais 23 secondes pour compiler sur le serveur.Regex lent sur Windows Server 2008

Des idées de quoi cela pourrait-il être responsable? Le problème est seulement sur la première utilisation de la Regex (quand il est d'abord compilé - par la suite il est bien)

J'ai également trouvé un autre problème - en utilisant \s+ dans l'expression régulière sur le même serveur Windows 2008, les ballons de mémoire (utilise 4GB +) et la compilation du Regex ne se termine jamais.

Existe-t-il un problème connu avec Regex et 64 bits .net? Y at-il un correctif/correctif disponible pour cela? Je ne peux pas vraiment trouver d'informations sur le net, mais j'ai trouvé quelques articles à propos de ces mêmes problèmes dans Framework 2.0 - cela a certainement été corrigé à ce jour?

Plus d'informations: Le serveur exécute la version 64 bits du framework .net (3.5 SP1) et sur mon ordinateur portable j'ai Visual Studio 2008 et le framework 3.5 installé. L'expression régulière est le schéma suivant: ^word$|^word$|^word$ et est construit avec les indicateurs suivants: RegexOptions.IgnoreCase | RegexOptions.Compiled


Voici un extrait de code:

StringBuilder regexString = new StringBuilder(); 
if (!String.IsNullOrEmpty(fileLocation)) 
{ 
    XmlTextReader textReader = new XmlTextReader(fileLocation); 
    textReader.Read(); 
    while (textReader.Read()) 
    { 
     textReader.MoveToElement(); 
     if (textReader.Name == "word") 
     { 
      regexString.Append("^" + textReader.GetAttribute(0) + "$|"); 
     } 
    } 
    ProfanityFilter = new Regex(regexString.ToString(0, regexString.Length - 1), RegexOptions.IgnoreCase | RegexOptions.Compiled); 
} 

DateTime time = DateTime.Now; 
Console.WriteLine("\nIsProfane:\n" + ProfanityFilter.IsMatch("test")); 
Console.WriteLine("\nTime: " + (DateTime.Now - time).TotalSeconds); 
Console.ReadKey(); 

Il en résulte un temps de 0,21 secondes sur mon ordinateur portable et 23 secondes sur le serveur 2008. Le fichier XML est composé de 168 mots dans le format suivant:

<word text="test" /> 
+3

Que diriez-vous de l'exemple de code, pour regex et xml? –

Répondre

4

J'ai trouvé une solution, pas la bonne, mais parfaite dans mon cas. Pour une raison quelconque, si je laisse de côté le drapeau RegexOptions.Compiled, le Regex est beaucoup, beaucoup plus rapide. J'ai même réussi à exécuter le Regex sur 100 longues phrases en moins de 65 millisecondes sur le serveur 2008.

Cela doit être un bogue dans la bibliothèque .net car la version non compilée est censée être beaucoup plus lente que la version compilée. De toute façon, moins de 1 milliseconde par chèque est très acceptable pour moi :)

+0

Vous pouvez également expérimenter avec plus de modèles alternatifs regex pour trouver le meilleur, comme/^ (mot | mot | mot | mot) $/au lieu de/^ mot $ |^mot $ |^mot $ /. – brianary

+0

Oui, j'en suis conscient. Comme je l'ai mentionné dans la question initiale, j'ai écrit une application console simplement pour mettre en évidence le problème. Ce même Regex compile en 0.21 secondes sur mon ordinateur portable, donc il ne devrait pas avoir besoin de compiler pendant 23 secondes sur un serveur 64 bits. – pjmyburg

+0

Avait le même problème et la solution, avec le jeu compilé il fonctionnait bien sur ma boîte d'XP locale, quand téléchargé sur le serveur prenait 40+ secondes par regex. L'option compilée supprimée et 8 appels prennent maintenant moins de 1 seconde au total. – ManiacZX

4

Vous pouvez pré-compiler vos regexes en utilisant la méthode Regex.CompileToAssembly, et vous pouvez déployer les expressions rationnelles compilées à votre serveur.

+0

Oui, mais cela signifie que les administrateurs non techniques du service ne peuvent pas simplement ajouter un mot à un fichier XML - les DLL doivent être recompilées à chaque fois. Bonne suggestion cependant. – pjmyburg

+1

Je pense qu'il voulait dire qu'après avoir lu dans le fichier, vous utilisez l'option RegexOptions.Compiled pour optimiser l'exécution de la regex. – brianary

+0

Non, il voulait dire que vous pré-compilez le Regex dans un fichier DLL (assembly) - c'est ce que fait la méthode CompileToAssembly. L'indicateur RegexOptions.Compiled est la cause de tout ce problème. C'est en effet la façon dont je voudrais aller, mais il semble qu'il y ait un bug dans les bibliothèques .net 64 bits. – pjmyburg

1

J'ai rencontré exactement le même problème. Mon application fonctionne correctement sur les ordinateurs x86 mais les bulles de mémoire et se bloque sur x64. Retrait de l'indicateur de compilation n'a pas aidé. J'ai essayé ceci aujourd'hui. Net 4.0 et le problème demeure. Si vous avez un repro, je vous suggère de déposer un bug.

Je pense MSFT sait à ce sujet, voir le fond comment here

Mais les laisser décider si tel est le même bug. S'il vous plaît ajouter un lien à votre dépôt ici si vous produisez afin que je puisse ajouter mes commentaires.

+0

J'ai rencontré le même problème avec l'application .NET 4.0 fonctionnant sur Windows Server 2008 r2 64 bit machine. Des nouvelles sur le sujet? Doron – DoronBM

+0

@DoronBM, veuillez commenter le lien de la base de données de bogues de Microsoft ci-dessus et travailler à l'escalader avec votre représentant de Microsoft. Merci! Autant que je sache, il n'y a pas eu de résolution. – Barka

Questions connexes