Dart中功能风格的性能提升

时间:2013-12-16 18:16:56

标签: performance functional-programming dart

我是否期望在Dart中使用纯功能样式(没有副作用)的性能提升?天真的我会期待相反,但我想象可能有更多的优化机会。

举一个例子,假设一个可以这样实现的矢量类:

class Vec {
  final num x, y, z;
  Vec(this.x, this.y, this.z);
  Vec add(Vec v) => new Vec(x + v.x, y + v.y, z + v.z);
}
final x = new Vec(1,2,3).add(new Vec(4,5,6));

vs这样的实现:

class Vec {
  num x, y, z;
  Vec(this.x, this.y, this.z);
  Vec add(Vec v) { x += v.x; y += v.y; z += v.z; return this; }
}
var x = new Vec(1,2,3).add(new Vec(4,5,6));

创建少一个Vec对象。 (显然可能有一种add(x,y,z)方法可以创建更少的Vec,但我想象添加的向量在现实生活中不是常数值。)

在Javascript VM中,据我所知,额外的对象创建相对昂贵,而且您不必在不必要时创建新对象。如果这是C ++,我会期望很多Vec对象会出现在堆栈中,我希望这两个对象之间的差异能够得到优化。

我认为纯函数式的主要可优化性增益是并行性,这可能不适用于Dart VM。

2 个答案:

答案 0 :(得分:1)

在Dart中使用运算符就像调用方法一样。由于隐式操作数转换,没有性能开销。

我相信VM非常好用于取消装箱的简单对象并将它们保留在堆栈中,尤其是在所有成员都是最终成员的情况下。因此,对于热代码,由于创建了额外的对象,因此不应对垃圾收集器施加额外的压力。

但是像马辛所说的那样 - 最好的方法就是知道这一点。

或许看一下Tracer benchmark源代码(这是一个简单的光线跟踪器)。我很确定这会使用运算符重载它的3D点和向量。这将让您了解javascript与Dart性能。您甚至可以删除+运算符调用并使用add()方法替换它们以查看是否存在很大差异。 (这可能比尝试创建微基准更有用。)

另外 - 也许你应该改变这个问题的标题 - 这不是pure functional programming。尽管Dart有一堆函数样式方法,例如map()和fold(),但它不支持纯函数式编程,因为它不支持正确的尾调用,这意味着纯函数式程序会导致堆栈溢出。

答案 1 :(得分:0)

好吧,我继续进行快速测试。基本上我只是根据每个实现添加了十亿个向量。功能性的需要大约三倍。因此,目前看来,至少目标创建并没有被优化掉。

void main() {
  const N = 1000000000;
  int i = 0;
  var v = new Vec(0,0,0);
  while (i < N * 3) {
    v = v.add(new Vec(i++, i++, i++));
  }
  print('$v');
}

我还尝试使用add(num,num,num)之类的语义实现,而不是add(new Vec(num,num,num)),从而消除了另一个临时对象。那甚至更快,但只是略微如此;让我相信编译器 设法部分优化了特定的临时对象创建。