.net – 正则表达式的多线程使用
鉴于以下来自MSDN:
我发现,对于性能,最好不要在使用ThreadLocal类时在线程之间共享Regex实例. 请问有人可以解释为什么线程本地实例的运行速度大约快5倍? 以下是结果(在8核机器上): Using Regex singleton' returns 3000000 and takes 00:00:01.1005695 Using thread local Regex' returns 3000000 and takes 00:00:00.2243880 源代码: using System; using System.Linq; using System.Threading; using System.Text.RegularExpressions; using System.Diagnostics; namespace ConsoleApplication1 { class Program { static readonly string str = new string('a',400); static readonly Regex re = new Regex("(a{200})(a{200})",RegexOptions.Compiled); static void Test(Func<Regex> regexGettingMethod,string methodDesciption) { Stopwatch sw = new Stopwatch(); sw.Start(); var sum = Enumerable.Repeat(str,1000000).AsParallel().Select(s => regexGettingMethod().Match(s).Groups.Count).Sum(); sw.Stop(); Console.WriteLine("'{0}' returns {1} and takes {2}",methodDesciption,sum,sw.Elapsed); } static void Main(string[] args) { Test(() => re,"Using Regex singleton"); var threadLocalRe = new ThreadLocal<Regex>(() => new Regex(re.ToString(),RegexOptions.Compiled)); Test(() => threadLocalRe.Value,"Using thread local Regex"); Console.Write("Press any key"); Console.ReadKey(); } } } 解决方法
发布我的调查结果.
我们是ILSpy Regex.它包含对RegexRunner的引用.当Regex对象匹配某些内容时,它会锁定其RegexRunner.如果对同一个Regex对象有另一个并发请求,则会创建另一个临时RegexRunner实例. RegexRunner价格昂贵.共享Regex对象的线程越多,浪费时间创建临时RegexRunner的机会就越多.希望微软能够解决这个大规模并行时代的问题. 另一件事:Regex类的静态成员将模式字符串作为参数(如Match.IsMatch(input,pattern))也必须在不同线程中匹配相同模式时执行得很糟糕. Regex维护着RegexRunners的缓存.具有相同模式的两个并发Match.IsMatch()将尝试使用相同的RegexRunner,并且一个线程将必须创建临时RegexRunner. 感谢Will让我知道你如何处理主题首发找到答案的问题. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |