【问题标题】:Difference between a Local Variable and a Variable Called from a Method? C#局部变量和从方法调用的变量之间的区别? C#
【发布时间】:2010-10-27 11:06:52
【问题描述】:

我想知道什么更快。帮帮我。

我在方法中声明了一个变量,如下所示:

    public static Regex FindNumber()
{ return new Regex(@"\d+", RegexOptions.IgnoreCase | RegexOptions.Compiled); }

如您所见,它返回一个正则表达式。

我还有另一种方法,看起来像这样:

    private static string TestOne(string RawData)
{
    Regex rgxFindNumber = FindNumber();
    Regex rgxFindDays = FindDays();
    for (int i = 0; i < mc.Count; i++)
    {
        int days = Convert.ToInt32(rgxFindNumber.Match(rgxFindDays.Match(mc[i].Value).Value).Value);
    }
    return RawData;
}

现在是 TestOne 方法更快还是 TestTwo 更快?

        private static string TestTwo(string RawData)
{
    for (int i = 0; i < mc.Count; i++)
    {
        int days = Convert.ToInt32(FindNumber().Match( FindDays().Match(mc[i].Value).Value).Value);
    }
    return RawData;
}

现在我很好奇,因为 TestOne 在我的代码中可能会被大量调用,所以我想知道什么会更好地实现。

谢谢大家。

**编辑:**我使用的代码有一个非常大的类。它是基于文本的策略游戏的文本解析器。我正在尝试对其进行一些重构,这就是我想知道的。如果我确实为 Regex 创建了一个私有变量,那么每次访问该类时不会运行它吗?这是我的问题。

【问题讨论】:

  • 首先设定有意义的绩效目标。其次,根据这些目标衡量进展情况。第三,如果你还没有达到你的目标,使用分析器找出最慢的东西。第四,修复它。重复直到你达到你的目标。每一步都至关重要。回答您的问题的唯一方法是尝试并衡量结果以查看它是否有意义。坐在办公桌前阅读您的问题的任何人都不可能知道客户机器上的差异有多大,或者这种差异对您的客户是否有意义,或者这是否是您应该寻求优化的地方。

标签: c# oop testing methods


【解决方案1】:

TestOne 将比TestTwo 快,因为您不会为每个循环迭代创建新的正则表达式。

这有两个好处:

  • 用于解析和构造正则表达式对象的时间只执行一次,而不是 mc.Count 次
  • 由于构建的对象更少,因此垃圾收集的压力更小。

但是,我会更进一步。如果您总是要返回相同的正则表达式,并且担心速度,我会将该正则表达式对象缓存在静态字段中。

例如,您可能会这样认为:

private static Regex _FindNumber;
public static Regex FindNumber()
{
    if (_FindNumber == null)
        _FindNumber = new Regex(@"\d+", RegexOptions.IgnoreCase | RegexOptions.Compiled);
    return _FindNumber;
}

这将只创建一个对象,总计,并保留它。

但是,这是我真正的答案。

要真正知道哪个会是最快的,您将不得不测量您的代码,可选择加入我的变体以进行良好测量,然后再决定。永远不要在没有硬数据的情况下决定优化,你最终可能会花时间重写代码,这可能会引入新的错误,需要修复,你会花更多的时间在这上面,只是为了再获得 1% 的性能。

大优化是通过算法完成的,例如更改排序算法的类型,然后仅在必要时进行局部优化,例如循环调整。

话虽如此,我至少会避免在循环中构造对象,这只是常识。

【讨论】:

  • 我将按照 womps 的回答重复此评论,因为它仍然适用。我使用的代码有一个非常大的类。它是基于文本的策略游戏的文本解析器。我正在尝试对其进行一些重构,这就是我想知道的。如果我确实为 Regex 创建了一个私有变量,那么每次访问该类时不会运行它吗?这是我的问题。
  • Scott:上面提供的代码在第一次访问 FindNumber 静态属性时创建了存储在 _FindNumber 中的 Regex,它将继续存在直到程序结束。
  • 每次调用返回新Regex对象的方法,都会得到一个新的Regex对象,这需要时间来构造,并增加GC压力。如果您缓存该对象,以便下次调用相同的函数时,它只会获取先前生成的对象,您将节省时间和 GC 压力。如果你在一个循环中调用该函数,并且它没有缓存,那么每次循环迭代都会花费更多时间,因为它构造了更多的对象,并增加了更多的 GC 压力。这是否回答你的问题?如果不是,请具体说明。
  • 更具体一点,我是 ASP.Net 中的基于 Web 的程序员。所以当我说它可以多次运行时,它将在每次页面刷新之后而不是在同一个“上下文”中,这意味着在每次服务器调用期间,都会创建一个新线程,然后再销毁。除非我将它缓存到 Session 中,否则无法在每个服务器调用之间保持该对象处于活动状态。现在,我不认为重构那么多会加快速度。我还能做些什么来阻止该方法自行重新创建它?
  • 请注意,静态字段将在整个 Web 应用程序中保留其值,这意味着跨不同用户和跨会话。
【解决方案2】:

从技术上讲,TestOne 会更快,因为 TestTwo 通过调用 FindNumber() 添加堆栈帧。

我不知道它会产生多大的不同,我怀疑它会产生多大的影响。你的方法是静态的,所以实际上它只是创建对象,应该很快。

我的问题是你为什么要使用函数调用来一遍又一遍地返回相同的字符串?为什么不直接声明一个真正的变量?

喜欢,

private static Regex _findNumber = new Regex(@"\d+", RegexOptions.IgnoreCase | RegexOptions.Compiled);

【讨论】:

  • 我使用的代码有一个非常大的类。它是基于文本的策略游戏的文本解析器。我正在尝试对其进行一些重构,这就是我想知道的。如果我确实为 Regex 创建了一个私有变量,那么每次访问该类时不会运行它吗?这是我的问题。
  • 每次访问类?绝对不。每次创建类时,当然 - 你会为它创建一个私有变量。但是仅仅取消引用一个变量会比调用一个函数来做同样的事情要快。
  • womp,由于它的大小,我将在一个类中拥有大约 100 个私有变量,但在任何实例上,每次创建一个类时只使用大约 3 或 4 个或这些变量。我是一名基于 Web 的程序员,据我所知,每次进行回发并调用类中的方法时,都会重新创建类。我对么?因此,由于每次“创建”类时我只使用这些新创建的变量中的 3 或 4 个,因此将每个变量放入一个方法中会更好。对吗?
  • 如果您将其设为静态,则不会。任何静态的东西都会被创建一次。事实上,如果您在 MyClass 中创建一个静态变量,您可以随时调用 MyClass.MyVariable,甚至无需创建 MyClass 的实例。它将被创建一次,就像您当前使用的当前函数一样,除了您不必调用函数。你可以在这里阅读:msdn.microsoft.com/en-us/library/79b3xss3.aspx
【解决方案3】:

我相信TestOne 会更快,因为在TestTwo 中,您每次循环时都会创建一个新的Regex 对象。如果FindDays 的实现方式与FindNumber 相同,则情况会更糟,因为您将创建两个对象。

【讨论】:

    猜你喜欢
    • 2022-06-16
    • 2015-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多