【问题标题】:Why is caching causing my code to run slower?为什么缓存会导致我的代码运行速度变慢?
【发布时间】:2011-03-19 21:48:42
【问题描述】:

非缓存:

var sw = Stopwatch.StartNew();
foreach (var str in testStrings)
{
    foreach (var pair in flex)
    {
        if (Regex.IsMatch(str, "^(" + pair.Value + ")$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture))
            ;
    }
}
Console.WriteLine("\nRan in {0} ms", sw.ElapsedMilliseconds); // 76 ms

缓存

var cache = flex.ToDictionary(p => p.Key, p => new Regex("^(" + p.Value + ")$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled));

var sw = Stopwatch.StartNew();
foreach (var str in testStrings)
{
    foreach (var pair in cache)
    {
        if(pair.Value.IsMatch(str))
            ;
    }
}
Console.WriteLine("\nRan in {0} ms", sw.ElapsedMilliseconds); // 263 ms

我不知道为什么当我预编译所有正则表达式时它的运行速度变慢。更不用说flex 上的迭代器也应该更慢,因为它需要做更多的计算。

这可能是什么原因造成的?


实际上,如果我关闭Compiled 开关,它在缓存时会在 8 毫秒内运行。我认为“编译”会在构造正则表达式时编译它。如果没有,什么时候这样做?

【问题讨论】:

  • 如果您不在此代码周围放置for 并运行它进行 1M 次左右的迭代,任何测量都可能会淹没在噪音中。
  • 它将正则表达式编译为 C# 代码,对吧?生成的代码是在循环外部还是内部 JIT?
  • @Jon:考虑到我在没有循环的情况下得到 263 毫秒,我认为 1M 正在推动它。 5000 次迭代,使用 cache 但未编译需要 3282 毫秒。编译需要3663ms。仍然有点慢,但幅度较小。
  • 刚发现正则表达式在第一次使用后被缓存在内存中,即使关闭了编译选项。
  • 恕我直言,这似乎很奇怪。您可以尝试使用单个正则表达式(不遍历字典),看看是否有任何显着差异?

标签: c# optimization


【解决方案1】:

Regex 实际上不仅在第一次使用时被缓存,而且在构造时被缓存(看看反射器中的 4.0 代码,在其他框架中可能并非如此)。

因此,这里最大的区别是:

  1. 在后者中有一些在前者中没有的微不足道的字符串连接,以及在 Regex 编译之外的构造开销。
  2. 在后者中迭代的集合与在前者中不同。

尚不清楚flex 是什么类型的集合。如果它不是字典,那么我一点也不会对此感到惊讶,因为字典在枚举方面并不是非常快,因此大多数其他集合都会击败它。

除此之外,后者确实不是缓存的情况,因为它正在缓存已经将从内存缓存中检索到的东西,因此没有理由怀疑后者会更快。

【讨论】:

  • 我在帖子中链接到 flex 类。枚举器实际上在内部使用了一个字典,然后在此基础上做了更多的工作。另外,我认为您在第一点交换了“前者”和“后者”,这一切都表明后者应该更快。无论如何,我已经得出结论,这些事情都不重要......我会发布我的答案。
【解决方案2】:

问题在于RegexOptions.Compiled 标志。这实际上使它运行得慢了很多。 Jeff 有点像explains this in his blog。没有这个标志,缓存的版本会快很多。

【讨论】:

  • 当编译的正则表达式用于许多字符串时,它们应该运行得更快。
  • Jenea:嗯,我不知道。当这是我唯一改变的事情时,编译集运行速度会变慢。
  • 如果你没有在第二个例子中添加 Compiled 标志,性能会改变吗?
  • @Janea:是的,正如我在上一段中所说,它实际上运行得更快。非缓存 = 76 毫秒,缓存 = 263 毫秒,缓存未编译 = 8 毫秒。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
  • 1970-01-01
  • 2018-11-30
  • 2021-12-14
  • 2016-10-23
  • 2012-01-02
相关资源
最近更新 更多