[C#][Regex] Hjälp med förbättra koden tar lång tid på sig

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016

[C#][Regex] Hjälp med förbättra koden tar lång tid på sig

Tja,

Håller på med Regex och den tar för låg tid ibland så fastna den i ett tag sen så fortsätter den igen.

Den tar ca 55 Sek på sig totalt och då söker den bara i 3k text filer.

public static Dictionary<string, string> regexlistas = new Dictionary<string, string>();

private void searchregex(string dir, string open) { #region regexlistas funder if (File.Exists(dir)) { foreach (var d in regexlistas) { Regex regex = new Regex(d.Key); Match match = regex.Match(open); if (match.Success == true) { form1.SaveFile(d.Value, dir); fond++; break; } } } #endregion }

Någon som har någon smart ide?

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Medlem
Registrerad
Sep 2016

Du kan ju pröva att skapa en Dictionary med färdiga RegExp i konstruktorn och köra med den istället för att skapa dem när du söker. Pröva också med RegexOptions.Compiled

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016
Skrivet av lrkss:

Du kan ju pröva att skapa en Dictionary med färdiga RegExp i konstruktorn och köra med den istället för att skapa dem när du söker. Pröva också med RegexOptions.Compiled

Hur skulle den se ut med "Dictionary med färdiga RegExp" har du någon tex?

Tänkte du på att man ska foreach dictionary?

Edit:

Hade du tänkte något åt det här hållet?

Test kod

private static List<Regex> test = new List<Regex>(); public static Dictionary<string, string> regexlistas = new Dictionary<string, string>();

foreach (var s in regexlistas) { var g = new Regex(s.Key, RegexOptions.Compiled); test.Add(g); }

foreach (Regex r in test) { Match match = r.Match("10.52.1.6"); if (match.Success == true) { Console.WriteLine(match.Value); } }

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Medlem
Registrerad
Sep 2016

Det var så jag tänkte det. Gick det något fortare ?

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016
Skrivet av lrkss:

Det var så jag tänkte det. Gick det något fortare ?

10 sek snabbare.

Match match = r.Match(open);

Jag testa bara med "test".

Match match = r.Match("test");

Då vart den mycket snabbare så vad ska man göra för att göra den snabbare med en stor text fil någon KB?

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Moderator
Registrerad
Aug 2007
Skrivet av superegg:

10 sek snabbare.

Match match = r.Match(open);

Jag testa bara med "test".

Match match = r.Match("test");

Då vart den mycket snabbare så vad ska man göra för att göra den snabbare med en stor text fil någon KB?

Jag gissar att det är komplexiteten på ditt regexp-uttryck som gör att det tar tid. Prova att förenkla uttrycket.

Använd gilla för att markera nyttiga inlägg!

Trädvy Permalänk
Medlem
Registrerad
Jul 2013

Inte kollat på din kod, men kanske Parallel.ForEach?
https://msdn.microsoft.com/en-us/library/dd460720(v=vs.110).a...

Trädvy Permalänk
Medlem
Registrerad
Sep 2016

Måste det vara textfiler eller kan det importeras till en databas istället ?

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016
Skrivet av giplet:

Jag gissar att det är komplexiteten på ditt regexp-uttryck som gör att det tar tid. Prova att förenkla uttrycket.

Det är något med att texten är stor då menar jag KB vet inte varför den tar tid på sig.

Skrivet av sickhouse:

Inte kollat på din kod, men kanske Parallel.ForEach?
https://msdn.microsoft.com/en-us/library/dd460720(v=vs.110).a...

Ska kolla mer på detta.

Skrivet av lrkss:

Måste det vara textfiler eller kan det importeras till en databas istället ?

Så klart jag kan lägga in det i database men fråga är om det mer snabbare.

För den ladda text filen sen skicka den till function så den är redan laddad eller har jag fel?

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Mar 2010

var & hur läser du in filerna som du skall matcha i?

Körs det i en rekursiv loop för sub-dirs? Är den loopen frisk?

// LZ

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016
Skrivet av Tea42BBS:

var & hur läser du in filerna som du skall matcha i?

Körs det i en rekursiv loop för sub-dirs? Är den loopen frisk?

// LZ

Så set loopen ut.

string[] files = Directory.GetFiles("Store", "*.txt"); foreach (string dir in files) { string filename = Path.GetFileNameWithoutExtension(dir); if (!cachelists.Contains(filename)) { string open = File.ReadAllText(dir); var task = Task.Run(() => search.search(dir, open)); tasks.Add(task); if (tasks.Count() == 3) { Task.WaitAll(tasks.ToArray()); tasks.Clear(); } cachelists.Add(filename); }

private void searchlistas(string dir, string open) { #region listas funder if (File.Exists(dir)) { foreach (string s in listas) { if (open.Contains(s)) { form1.SaveFile(s, dir); fond++; break; } } } #endregion } private void searchregex(string dir, string open) { #region regexlistas funder if (File.Exists(dir)) { foreach (var d in regexlistas) { Regex regex = new Regex(d.Key); Match match = regex.Match(open); if (match.Success == true) { form1.SaveFile(d.Value, dir); fond++; break; } } } #endregion } public void search(string dir, string open) { //searchlistas(dir, open); searchregex(dir, open); }

Den nya test koden som jag hade innan är inte med i denna.

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Medlem
Registrerad
Sep 2016

Måste du matcha hela texten eller kan du läsa in rad per rad och sedan avbryta när den matchar en rad ?

Annars får du nog visa lite exempel data och hur regex uttrycken ser ut.

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016
Skrivet av lrkss:

Måste du matcha hela texten eller kan du läsa in rad per rad och sedan avbryta när den matchar en rad ?

Annars får du nog visa lite exempel data och hur regex uttrycken ser ut.

Jag har nu felsök ett tag och kom framtill att den har visa problem med visa text filer.

En text fil är bara 3 kB och tar 900 ms på sig.

Jag prova med att ladda en rad i taget men det bliv ändå inte snabbare.

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Medlem
Registrerad
Sep 2016
Trädvy Permalänk
Moderator
Registrerad
Aug 2007
Skrivet av lrkss:

Ja, det var typ det jag menade i mitt inlägg ovan. När man skriver lite mer komplexa regexp-uttryck är det lätt att det drar iväg i tidsåtgång. Denna tolkning gjorde jag eftersom ett enkelt uttryck går mycket fortare att köra. Lösningen är att optimera sina uttryck. Regexp kan vara väldigt snabbt och effektivt, men kan också vara horribelt långsamt.

Använd gilla för att markera nyttiga inlägg!

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011

Kombinationen reguljära uttryck och C#/.NET kanske inte är helt optimalt. Googlar man på detta hittar man rätt mycket klagomål på att regexp-motorn är långsam, verkar helt enkelt inte något man lagt speciellt mycket tid på att optimera.

En vink om att så är fallet får man här. Relativt enkla reguljära uttryck, att språk som PHP och Node.JS (JS) ligger i topp ska inte tolkas som att dessa språk generellt sett är supersnabba utan man har helt enkelt lagt väldigt mycket krut på att optimera deras regexp-motororer (som i båda fallen är skrivna i C/C++).

C# .NET Core är faktiskt bland det långsammare alternativen här, t.ex. är Ruby och Python dubbelt så snabba. Att det inte har något med hur snabb plattformen rent generellt är ser man då Go, som i normalfallet är i nivå med C och C++ när det handlar om ren kod, också ligger rejält efter de språk där reguljära uttryck används väldigt mycket.

Känns som det du försöker göra skulle vara långt enklare i t.ex. ett bash-skript. Att lista filer, köra sökningar baserat på reguljära uttryck samt lägga ut jobb på en maximal antal "workers" är ju standardfunktioner i bash (find, xargs, egrep m.fl.).

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016
Skrivet av giplet:

Ja, det var typ det jag menade i mitt inlägg ovan. När man skriver lite mer komplexa regexp-uttryck är det lätt att det drar iväg i tidsåtgång. Denna tolkning gjorde jag eftersom ett enkelt uttryck går mycket fortare att köra. Lösningen är att optimera sina uttryck. Regexp kan vara väldigt snabbt och effektivt, men kan också vara horribelt långsamt.

Skrivet av Yoshman:

Kombinationen reguljära uttryck och C#/.NET kanske inte är helt optimalt. Googlar man på detta hittar man rätt mycket klagomål på att regexp-motorn är långsam, verkar helt enkelt inte något man lagt speciellt mycket tid på att optimera.

En vink om att så är fallet får man här. Relativt enkla reguljära uttryck, att språk som PHP och Node.JS (JS) ligger i topp ska inte tolkas som att dessa språk generellt sett är supersnabba utan man har helt enkelt lagt väldigt mycket krut på att optimera deras regexp-motororer (som i båda fallen är skrivna i C/C++).

C# .NET Core är faktiskt bland det långsammare alternativen här, t.ex. är Ruby och Python dubbelt så snabba. Att det inte har något med hur snabb plattformen rent generellt är ser man då Go, som i normalfallet är i nivå med C och C++ när det handlar om ren kod, också ligger rejält efter de språk där reguljära uttryck används väldigt mycket.

Känns som det du försöker göra skulle vara långt enklare i t.ex. ett bash-skript. Att lista filer, köra sökningar baserat på reguljära uttryck samt lägga ut jobb på en maximal antal "workers" är ju standardfunktioner i bash (find, xargs, egrep m.fl.).

Svar till båda!

GG det är denna uttryck som tog långa tid.
För att leta efter email måste hitta något som är bättre och snabbare utan denna så tog det 7 sek och inte 50 sek.

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2007

@superegg: Att parsa email-adresser med regexp är ju ökänt för att vara lurigt.

Vad för typ av text läser du? Vet du att det bara är mailadresser som innehåller @ kan du ju förenkla uttrycket (då kan du ju förvisso fånga "mailadresser" som inte är mailadresser) - men det är ju en avvägning du får göra.

WS: Bärbar workstation, 2 * Dell U2412M
HTPC: Intel NUC, Canton GLE 496, Yamaha RV-A830, Sanyo PLV-Z700
Server: Intel Xeon E3-1240@3.4 GHz, ESXi, 32GB RAM, 8*2TB RAID-Z2 + SSD-cache
Slösurf: MacBook Air 11,6", Samsung S8
Kamera: Canon EOS 5DII + 1DIII, Canon 100/2.8 Macro, Canon 70-200/2.8L, Canon 24-70/2.8L

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011

Om du har installerat Cygwin eller ännu bättre "bash" i Windows 10 anniversary update , testa detta

time find . -name "*.txt" -print0 | xargs -0 -n 20 -P 2 grep -E -o "\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}\b"

På min gamla MBP från 2009 (Core2 med två kärnor @ 2,4 GHz) tar det 32 sekunder att söka igenom ~310 MB av text i totalt 2934 textfiler. Det finns totalt 376 st email addresser i dessa textfiler...

Argumentet "-P WORKERS" till xargs styr hur många samtida regex-sökningar du vill ha samtidigt. Min MBP har bara två kärnor och ingen HT, så kör med två.

Reguljäruttrycket som används är en anpassning för syntax för e-mail addresser som beskrivs i kapitel 3.4 i RFC 5322.

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2008

Om du är intresserad av att göra en alternativ lösning, kan du kolla på hur du tar ut e-post adresser med hjälp av pythons regex. Jag skulle vilja argumentera för att hela din lösning kan göras i python relativt enkelt, däremot vågar jag inte säga huruvida pythons trådar är bra eller dåliga, då jag ej har utnyttjat de. Följande länk tar dig till googles egna dokumentation om hur du använder regex, med ett enkelt exempel på hur du kan få ut e-post adresser.

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Mar 2010

Denna kanske kan vara till hjälp:

http://www.regular-expressions.info/email.html

Jag har aldrig haft några prestanda problem med c# / .NET med kod som är ok skriven. Man kan alltid prata om mest optimerade motorn hitan o ditan, men grejen är att de flesta av oss sitter på cpu:er som kan massakrerea hundratals mb i sekunden utan att svettas.

// LZ

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Jul 2016
Skrivet av Tea42BBS:

Denna kanske kan vara till hjälp:

http://www.regular-expressions.info/email.html

Jag har aldrig haft några prestanda problem med c# / .NET med kod som är ok skriven. Man kan alltid prata om mest optimerade motorn hitan o ditan, men grejen är att de flesta av oss sitter på cpu:er som kan massakrerea hundratals mb i sekunden utan att svettas.

// LZ

Ska kolla på det som du har länkat och testa om den blir snabbare av det gör det när jag är lite mer piggare är lite morgon trött just nu.

Skulle inte säga att min CPU är dålig. hehe

Kör esxi så den kanske inte kommer upp snabb i GHz.

Man är inte dum för att man har stavproblem.
Läs mer om min synfel Visual Snow
Om mig ----> #16970666

Trädvy Permalänk
Datavetare
Plats
Stockholm
Registrerad
Jun 2011
Skrivet av Tea42BBS:

Denna kanske kan vara till hjälp:

http://www.regular-expressions.info/email.html

Jag har aldrig haft några prestanda problem med c# / .NET med kod som är ok skriven. Man kan alltid prata om mest optimerade motorn hitan o ditan, men grejen är att de flesta av oss sitter på cpu:er som kan massakrerea hundratals mb i sekunden utan att svettas.

// LZ

Finns ju en anledning att majoriteten av alla program utan program kan utvecklas i "långsamma" språk som Ruby och Python, är väldigt få program där flaskhalsen verkligen är rå beräkningskraft. Att språk som C, C++ och Go, som alla är relativt "low-level", fortfarande används är att de är bästa val i de få fall när rå beräkningskraft faktiskt är en flaskhals.

I just detta fall har ju TS ändå ett problem som är begränsat av rå beräkningskraft, inte i det som skrivs i C# utan i plattformens regex-motor. Och har man ett sådan fall är just .NET ett väldigt dåligt alternativ då det finns andra regex-implementationer som är närmare en tiopotens snabbare. Att till och med språk som Python och Ruby kan vara snabbare på detta är ju enbart beroende på att de har bättre optimerade regex-motorer, hade det varit kod skriven i respektive programspråk hade rimligen C#/.NET varit klart snabbare.

Och det specifika fall TS har löses rimligen både snabbare och enklare i skriptspråk eller till och med i direkt i ett skal, just för att man i dessa lägen kan jobba med betydligt effektivare regex-motorer då detta är den absolut största flaskhalsen för detta problem.

Care About Your Craft: Why spend your life developing software unless you care about doing it well? - The Pragmatic Programmer