Created
November 28, 2014 10:04
-
-
Save cybermaxs/654414d3cdd2634e925a to your computer and use it in GitHub Desktop.
c# regular expression optimization for http://julien-fiaffe.com/2014/11/27/coding-tips-regex-optimization-in-csharp/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Text.RegularExpressions; | |
namespace RegexOptims | |
{ | |
public static class RegexComparer | |
{ | |
private const string REGEX_PATTERN = @"^[\w\d]+$"; | |
private const string REGEX_PATTERN_OPT = @"^[a-zA-Z0-9]+$"; | |
private const string REGEX_PATTERN_INV = @"^[^a-zA-Z0-9]+$"; | |
private const string REGEX_INPUT_TRUE = "azertyuiop7894561230qsdfghjklm7894561230wxcvbn7894561230"; | |
private const string REGEX_INPUT_FALSE = "az-io|p7894561230qsdfgh`jklm78945*61230wxcvbn789^4561230"; | |
public static bool StaticRegexMatch(bool truereg = true) | |
{ | |
var match = Regex.Match(truereg ? REGEX_INPUT_TRUE : REGEX_INPUT_FALSE, REGEX_PATTERN); | |
return match.Success; | |
} | |
public static bool StaticCompiledRegexMatch(bool truereg = true) | |
{ | |
var match = Regex.Match(truereg ? REGEX_INPUT_TRUE : REGEX_INPUT_FALSE, REGEX_PATTERN, RegexOptions.Compiled); | |
return match.Success; | |
} | |
private static Regex CompiledStaticRegexInstance = new Regex(REGEX_PATTERN, RegexOptions.Compiled); | |
public static bool CompiledRegexStaticInstanceMatch(bool truereg = true) | |
{ | |
var match = CompiledStaticRegexInstance.Match(truereg ? REGEX_INPUT_TRUE : REGEX_INPUT_FALSE); | |
return match.Success; | |
} | |
private static Regex CompiledStaticRegexInstanceOpt = new Regex(REGEX_PATTERN_OPT, RegexOptions.Compiled); | |
public static bool CompiledRegexStaticInstanceMatchOpt(bool truereg = true) | |
{ | |
var match = CompiledStaticRegexInstanceOpt.Match(truereg ? REGEX_INPUT_TRUE : REGEX_INPUT_FALSE); | |
return match.Success; | |
} | |
private static Regex CompiledStaticRegexInstanceInv = new Regex(REGEX_PATTERN_INV, RegexOptions.Compiled); | |
public static bool CompiledRegexStaticInstanceMatchInv(bool truereg = true) | |
{ | |
var match = CompiledStaticRegexInstanceInv.Match(truereg ? REGEX_INPUT_TRUE : REGEX_INPUT_FALSE); | |
return !match.Success; | |
} | |
public static bool LinqMatch(bool truereg = true) | |
{ | |
return (truereg ? REGEX_INPUT_TRUE : REGEX_INPUT_FALSE).All(c => char.IsLetterOrDigit(c)); | |
} | |
public static bool WhileMatch(bool truereg = true) | |
{ | |
var target = truereg ? REGEX_INPUT_TRUE : REGEX_INPUT_FALSE; | |
for (var i = 0; i < target.Length; i++) | |
{ | |
if (!char.IsLetterOrDigit(target[i])) | |
return false; | |
} | |
return true; | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
Console.WriteLine("Regex test"); | |
const int its = 100000; | |
bool truereg = true; | |
//from techblog | |
Profile("StaticRegexMatch", its, () => { return RegexComparer.StaticRegexMatch(truereg); }); | |
Profile("StaticCompiledRegexMatch", its, () => { return RegexComparer.StaticCompiledRegexMatch(truereg); }); | |
Profile("CompiledRegexStaticInstanceMatch", its, () => { return RegexComparer.CompiledRegexStaticInstanceMatch(truereg); }); | |
Profile("LinqMatch", its, () => { return RegexComparer.LinqMatch(truereg); }); | |
// ideas | |
Profile("CompiledRegexStaticInstanceMatchOpt", its, () => { return RegexComparer.CompiledRegexStaticInstanceMatchOpt(truereg); }); | |
Profile("CompiledRegexStaticInstanceMatchInv", its, () => { return RegexComparer.CompiledRegexStaticInstanceMatchInv(truereg); }); | |
Profile("Match", its, () => { return RegexComparer.WhileMatch(truereg); }); | |
Console.WriteLine("END"); | |
Console.ReadKey(); | |
} | |
static void Profile(string description, int iterations, Func<bool> func) | |
{ | |
// clean up | |
GC.Collect(); | |
GC.WaitForPendingFinalizers(); | |
GC.Collect(); | |
// warm up | |
var res = func(); | |
var watch = new Stopwatch(); | |
watch.Start(); | |
for (int i = 0; i < iterations; i++) | |
{ | |
func(); | |
} | |
watch.Stop(); | |
Console.WriteLine("Profile via an Action - " + description + " res =>" + res); | |
Console.WriteLine("{0:0.00} ms ({1:N0} ticks) (over {2:N0} iterations), {3:N0} ops/millisecond\n", | |
watch.ElapsedMilliseconds, watch.ElapsedTicks, iterations, (double)iterations / watch.ElapsedMilliseconds); | |
} | |
} | |
} | |
// restuls | |
// Regex test | |
// Profile via an Action - StaticRegexMatch res =>True | |
// 396,00 ms (965989 ticks) (over 100000 iterations), 253 ops/millisecond | |
// Profile via an Action - StaticCompiledRegexMatch res =>True | |
// 337,00 ms (822012 ticks) (over 100000 iterations), 297 ops/millisecond | |
// Profile via an Action - CompiledRegexStaticInstanceMatch res =>True | |
// 307,00 ms (747888 ticks) (over 100000 iterations), 326 ops/millisecond | |
// Profile via an Action - LinqMatch res =>True | |
// 84,00 ms (205805 ticks) (over 100000 iterations), 1190 ops/millisecond | |
// Profile via an Action - CompiledRegexStaticInstanceMatchOpt res =>True | |
// 149,00 ms (364012 ticks) (over 100000 iterations), 671 ops/millisecond | |
// Profile via an Action - CompiledRegexStaticInstanceMatchInv res =>True | |
// 14,00 ms (36236 ticks) (over 100000 iterations), 7143 ops/millisecond | |
// Profile via an Action - Match res =>True | |
// 27,00 ms (66854 ticks) (over 100000 iterations), 3704 ops/millisecond | |
// END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment