2009-09-29 14 views
5

Ho una situazione in cui le mie espressioni regolari vengono compilate estremamente lentamente su Windows Server 2008. Ho scritto una piccola applicazione console per evidenziare questo problema. L'app genera il proprio input e crea un Regex da parole in un file XML. Ho creato una versione di rilascio di questa app e l'ho eseguita sia sul mio laptop personale (con XP in esecuzione) che sul server Windows 2008. L'espressione regolare ha richiesto 0,21 secondi per la compilazione sul mio portatile, ma 23 secondi per la compilazione sul server.Regex lento su Windows Server 2008

Qualche idea che cosa potrebbe causare questo? Il problema è solo al primo utilizzo del Regex (quando viene compilato per la prima volta - quindi va bene)

Ho anche trovato un altro problema - quando si utilizza \s+ nell'espressione regolare sullo stesso server Windows 2008, i palloncini di memoria (usa 4 GB +) e la compilazione del Regex non finisce mai.

C'è un problema noto con Regex e 64 bit .net? C'è una correzione/patch disponibile per questo? Non riesco a trovare alcuna informazione in rete, ma ho trovato alcuni articoli su questo stesso problema in Framework 2.0 - sicuramente questo è stato risolto?

Altre informazioni: Il server sta eseguendo la versione a 64 bit del framework .net (3.5 SP1) e sul mio computer portatile ho Visual Studio 2008 e il framework 3.5 installato. L'espressione regolare è il seguente schema: ^word$|^word$|^word$ ed è costruito con i seguenti flag: RegexOptions.IgnoreCase | RegexOptions.Compiled


Ecco un frammento di codice:

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(); 

Ciò si traduce in un tempo di 0,21 secondi sul mio portatile e 23 secondi sul server 2008. Il file XML si compone di 168 parole del seguente formato:

<word text="test" /> 
+3

Come su esempio di codice, per regex e xml? –

risposta

4

Ho trovato una soluzione, data non quella giusta, ma perfetta nel mio caso. Per qualche motivo, se tralascio il flag RegexOptions.Compiled, lo Regex è molto, molto più veloce. Sono persino riuscito a eseguire lo Regex su 100 frasi lunghe in meno di 65 millisecondi sul server 2008.

Questo deve essere un bug nella .net lib poichè la versione non compilata dovrebbe essere molto più lenta della versione compilata. Ad ogni modo, meno di 1 millisecondo per assegno è per me molto accettabile :)

+0

Si potrebbe anche voler sperimentare più schemi regex alternativi per trovare quello ottimale, come/^ (parola | parola | parola | parola) $/invece di/^ parola $ |^parola $ |^parola $ /. – brianary

+0

Sì, ne sono consapevole. Come ho accennato nella domanda originale, ho scritto un'applicazione per console semplicemente per evidenziare il problema. Quello stesso esatto Regex si compila in 0,21 secondi sul mio portatile, quindi non dovrebbe aver bisogno di compilare per 23 secondi su un server a 64 bit. – pjmyburg

+0

Avendo lo stesso problema e la stessa soluzione, con la sua configurazione compilata, funzionava correttamente sul mio XP box locale, quando il caricamento sul server richiedeva 40+ secondi per regex. Rimosso l'opzione compilata e 8 chiamate ora richiedono meno di 1 secondo totale. – ManiacZX

4

È possibile pre-compilare i vostri espressioni regolari con il metodo Regex.CompileToAssembly, e quindi si potrebbe schierare le regex compilato al server.

+0

Sì, ma ciò significa che gli amministratori non tecnici del servizio non possono semplicemente aggiungere una parola a un file XML - le DLL devono essere ricompilate ogni volta. Buon suggerimento però – pjmyburg

+1

Penso che intendesse che dopo aver letto il file, si utilizza l'opzione RegexOptions.Compiled per ottimizzare l'esecuzione della regex. – brianary

+0

No, intendeva precompilare il Regex in un file DLL (assembly) - questo è ciò che fa il metodo CompileToAssembly. Il flag RegexOptions.Compiled è la causa di questo intero problema. Questo è davvero il modo in cui vorrei andare, ma sembra che ci sia un bug nelle librerie .net a 64 bit. – pjmyburg

1

Mi sono imbattuto nello stesso identico problema. La mia app funziona perfettamente su macchine x86 ma mollette di memoria e si blocca su x64. La rimozione del flag di compilazione non ha aiutato. Ho provato questo oggi su. NET 4.0 e il problema rimane. Se hai una riproduzione, ti suggerisco di presentare un bug.

penso MSFT sa di questo, vedere il fondo comment here

Ma lasciarli decidere se questo è lo stesso bug. Si prega di aggiungere un link al tuo archivio qui se file così posso aggiungere i miei commenti ad esso.

+0

Ho incontrato lo stesso problema con l'applicazione .NET 4.0 in esecuzione su Windows Server 2008 r2 a 64 bit. Eventuali notizie sull'argomento? Doron – DoronBM

+0

@DoronBM, si prega di commentare il link del database dei bug di Microsoft sopra e lavorare per inoltrarlo con il proprio rappresentante Microsoft. Grazie! Per quanto ne so non c'è stata alcuna risoluzione. – Barka

Problemi correlati