Skip to content
This repository has been archived by the owner on Feb 22, 2018. It is now read-only.

Commit

Permalink
perf(bracket): Optimize calling methods on objects.
Browse files Browse the repository at this point in the history
Optimize the closures used for calling methods on objects by getting rid
of an intermediate "field access" that loads the function from the object.
This allows us to use InstanceMirror.invoke more directly.

Performance
===========
The performance implications of this change look good. On the native Dart VM,
calling methods through the reflective path becomes 4.5x faster. When compiled
to JavaScript, the difference is even bigger and it is 6.7x faster.

Dart VM:
  new: o.f() => g: 18,885,385.384 ops/sec  r: 2,252,149.057 ops/sec   h: 2,233,514.96 ops/sec   i: 32,662,458.941 ops/sec
  old: o.f() => g: 18,118,349.692 ops/sec  r:   496,119.238 ops/sec   h: 6,234,893.68 ops/sec   i: 31,472,943.499 ops/sec

Dart2js:
  new: o.f() => g:  2,618,328.337 ops/sec  r: 1,234,723.632 ops/sec   h: 1,234,745.10 ops/sec   i:  7,507,441.131 ops/sec
  old: o.f() => g:  2,427,133.253 ops/sec  r:   184,727.903 ops/sec   h:   500,226.70 ops/sec   i:  7,461,638.467 ops/sec

Conflicts:
	lib/core/parser/backend.dart
  • Loading branch information
Kasper Lund authored and mhevery committed Jan 3, 2014
1 parent c279fac commit 12f5f67
Showing 1 changed file with 26 additions and 8 deletions.
34 changes: 26 additions & 8 deletions lib/core/parser/backend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,15 @@ class ParserBackend {
};
}

List evalList(List<Expression> list, self) {
int length = list.length;
List result = new List(length);
for (int i = 0; i < length; i++) {
result[i] = list[i].eval(self);
}
return result;
}

_op(opKey) => OPERATORS[opKey];

Expression ternaryFn(Expression cond, Expression _true, Expression _false) =>
Expand Down Expand Up @@ -237,16 +246,23 @@ class ParserBackend {
return value;
});

Expression functionCall(fn, fnName, argsFn, evalError) =>
new Expression((self){
List args = [];
for ( var i = 0; i < argsFn.length; i++) {
args.add(argsFn[i].eval(self));
}
Expression functionCall(fn, fnName, argsFn, evalError) {
if (fn.isFieldAccess) {
Symbol key = new Symbol(fn.fieldName);
return new Expression((self) {
List args = evalList(argsFn, self);
var holder = fn.fieldHolder.eval(self);
InstanceMirror instanceMirror = reflect(holder);
return instanceMirror.invoke(key, args).reflectee;
});
} else {
return new Expression((self) {
List args = evalList(argsFn, self);
var userFn = safeFunctionCall(fn.eval(self), fnName, evalError);

return relaxFnApply(userFn, args);
});
}
}

Expression arrayDeclaration(elementFns) =>
new Expression((self){
Expand Down Expand Up @@ -276,7 +292,9 @@ class ParserBackend {
var getterFn = getter(field);
return new Expression(
(self) => getterFn(object.eval(self)),
(self, value) => setterFn(object.eval(self), value));
(self, value) => setterFn(object.eval(self), value))
..fieldHolder = object
..fieldName = field;
}

Expression object(keyValues) =>
Expand Down

0 comments on commit 12f5f67

Please sign in to comment.