【问题标题】:Dart: Is it efficient to write nested functions in methods that are called several timesDart:在多次调用的方法中编写嵌套函数是否有效
【发布时间】:2021-01-19 08:20:39
【问题描述】:

请考虑以下代码,

class A {
  foo() {
    int a = logicToGetA();

    int _bar() => someOtherLogic(a);

    // ..

    int b = _bar();

    // ..
  }
}

class B {
  int _bar(int a) => someOtherLogic(a);

  foo() {
    int a = logicToGetA();

    // ..

    int b = _bar(a);

    // ..
  }
}

main() {
  for (int i = 0; i < 1000000; i++) {
    A().foo();
  }
  for (int i = 0; i < 1000000; i++) {
    B().foo();
  }
}

解释:A 类的 bar() 嵌套在 foo() 中,但 B 类的 bar() 嵌套在 foo() 之外。在第二种情况下,bar() 也可以作为静态方法。

我的疑问:如果 foo() 被多次调用,哪种方式更有效?如果 A().foo() 被调用 1000000 次,A.foo.bar 会被重新定义那么多次吗?

【问题讨论】:

  • 为什么这么多非母语人士说“我有疑问”,而他们的意思是“我有一个问题”?问题是中性的,怀疑意味着对情况或答案的某种怀疑。只是好奇。
  • “一个疑问”对于大多数其他英语语言中所谓的“问题”来说是完全正确的印度英语。 (english.stackexchange.com/questions/294125/…)
  • 我认为“怀​​疑”是一种谦虚的提问方式,即“我明白你的意思,但我需要一点澄清”。而“问题”可能不那么尊重。就像上面给出的询问示例。
  • 我向您的专业知识低头。非母语印度英语的人很容易忽略这些细微差别。我自学将“怀疑”理解为“问题”,到目前为止,这对我在国际公司工作很有效,可能是因为“问题”这个词在美式/英式英语中是中性的(至少对我而言)。
  • @lrn 你的方法更合理。我应该避免使用“怀疑”作为可数名词。

标签: performance dart nested-function


【解决方案1】:

视情况而定。

如果_bar 函数可以在foo 方法之外定义,那么我们可以假定它没有引用foo 方法的任何局部变量。 在这种情况下,编译器可以优化本地函数,使其与实例方法一样高效。也许有,也许没有,所以让我们检查一下。

请参阅:https://dartpad.dev/4a53a91bf4e0006e4af4c8a598b68ee6。 这是(尝试)编写的,以便编译器无法优化 _someOtherLogic 的调用。 我还尝试将调用设为静态方法(但随后必须将对象本身作为参数传递给flag 的实例 getter 的访问权限)。

在 dartpad 中运行它会给我一组最终结果

A: 918460 /ms
B: 798960 /ms
S: 918380 /ms

似乎 dart2js 使用本地函数比使用实例方法更有效。 在 VM 上运行相同的代码会得到以下基准测试结果:

A: 625960.0 /ms
B: 723245.0 /ms
S: 625075.0 /ms

表明它的性能特点与 dart2js 完全相反。

dart2js 很可能在静态已知时内联了 _bar 函数。 dart2js 编译器比 VM 更倾向于内联。

总而言之,我不会开始担心这种差异,除非函数调用大量出现在实际程序的性能配置文件中。 如果您的程序的性能真的严重依赖于这个 one 函数调用,我可能会内联该函数。如果不是,请编写更具可读性和可维护性的内容,并且在您知道重要之前不要开始进行微优化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-09
    • 2014-06-01
    相关资源
    最近更新 更多