Promise performance slow?

154 views
Skip to first unread message

dpa...@chromium.org

unread,
Aug 6, 2015, 7:45:09 PM8/6/15
to v8-users
Hi,

I was comparing native Promise performance with goog.Promise (from https://closure-library.googlecode.com/git-history/docs/local_closure_goog_promise_promise.js.source.html).
I was surprised that the JS version is much faster, example snippets below.

var testFn = function(constructorFn, allFn) {
  var count = 10000;
  var promises = new Array(count);
  var start = performance.now();
  for (var i = 0; i < promises.length; i++) {
    promises[i] = new constructorFn(function(res, rej) { res(i); });
  };
  allFn(promises).then(function() { console.log(performance.now() - start); });
}

testFn(Promise, Promise.all.bind(Promise));          // ~500ms, binding necessary because of crbug.com/517668
testFn(Promise, goog.Promise.all);                        // 600ms
testFn(goog.Promise, Promise.all.bind(Promise)); // ~1500ms
testFn(goog.Promise, goog.Promise.all);               // ~85ms

Using both goog.Promise and goog.Promise.all seems much faster than any of the other three calls where either Promise constructor, or Promise.all static method is involved. Is there
any room for optimization in native Promises?

Thank you,
Demetrios

Andreas Rossberg

unread,
Aug 7, 2015, 3:33:52 AM8/7/15
to v8-u...@googlegroups.com
On 7 August 2015 at 01:45, <dpa...@chromium.org> wrote:
I was comparing native Promise performance with goog.Promise (from https://closure-library.googlecode.com/git-history/docs/local_closure_goog_promise_promise.js.source.html).
I was surprised that the JS version is much faster, example snippets below.

This is a known problem. Several reasons:

1. V8 promises haven't been optimised at all. It's on our agenda once our ES6 support is feature complete.
2. V8 promises support various callback hooks into devtools, which cause a certain overhead.
3. Alternative promise implementations tend to take shortcuts relative to the official ES6 semantics (e.g., goog.Promise.all you use below does not support subclassing correctly).

We assume that (1) is the main factor, and will go away eventually, but due to the others some (hopefully minor) differences might remain.

Also, add the usual caveat about micro benchmarks. Does this measurably affect real applications?

/Andreas


var testFn = function(constructorFn, allFn) {
  var count = 10000;
  var promises = new Array(count);
  var start = performance.now();
  for (var i = 0; i < promises.length; i++) {
    promises[i] = new constructorFn(function(res, rej) { res(i); });
  };
  allFn(promises).then(function() { console.log(performance.now() - start); });
}

testFn(Promise, Promise.all.bind(Promise));          // ~500ms, binding necessary because of crbug.com/517668
testFn(Promise, goog.Promise.all);                        // 600ms
testFn(goog.Promise, Promise.all.bind(Promise)); // ~1500ms
testFn(goog.Promise, goog.Promise.all);               // ~85ms

Using both goog.Promise and goog.Promise.all seems much faster than any of the other three calls where either Promise constructor, or Promise.all static method is involved. Is there
any room for optimization in native Promises?

Thank you,
Demetrios

--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Andreas Rossberg

unread,
Aug 7, 2015, 3:45:48 AM8/7/15
to v8-u...@googlegroups.com
I should also add that your micro benchmark might be skewed by the use of .bind, which is known to be slow currently.

/Andreas

dpa...@chromium.org

unread,
Aug 7, 2015, 12:58:09 PM8/7/15
to v8-users, Arthur Hsu
Thanks for the detailed explanation and roadmap.
Answers inlined.


On Friday, August 7, 2015 at 12:45:48 AM UTC-7, Andreas Rossberg wrote:
I should also add that your micro benchmark might be skewed by the use of .bind, which is known to be slow currently.
Is the call to bind() itself slow, or calling a function after it has been bound makes it execute slower? The former would not matter, since I am calling bind() before starting the timer. The latter (which I think I have observed in the past) would indeed skew the results if true.

 

/Andreas


On 7 August 2015 at 09:33, Andreas Rossberg <ross...@google.com> wrote:
On 7 August 2015 at 01:45, <dpa...@chromium.org> wrote:
I was comparing native Promise performance with goog.Promise (from https://closure-library.googlecode.com/git-history/docs/local_closure_goog_promise_promise.js.source.html).
I was surprised that the JS version is much faster, example snippets below.

This is a known problem. Several reasons:

1. V8 promises haven't been optimised at all. It's on our agenda once our ES6 support is feature complete.
2. V8 promises support various callback hooks into devtools, which cause a certain overhead.
3. Alternative promise implementations tend to take shortcuts relative to the official ES6 semantics (e.g., goog.Promise.all you use below does not support subclassing correctly).

We assume that (1) is the main factor, and will go away eventually, but due to the others some (hopefully minor) differences might remain.

Also, add the usual caveat about micro benchmarks. Does this measurably affect real applications?
I believe it does. Have not proved it yet, but it's easy. I will replace goog.Promise with Promise in some of Lovefield's code (https://github.com/google/lovefield) which makes heavy use of goog.Promise and come back with an answer to this.

Andreas Rossberg

unread,
Aug 7, 2015, 1:05:00 PM8/7/15
to v8-u...@googlegroups.com, Arthur Hsu
On 7 August 2015 at 18:58, <dpa...@chromium.org> wrote:
On Friday, August 7, 2015 at 12:45:48 AM UTC-7, Andreas Rossberg wrote:
I should also add that your micro benchmark might be skewed by the use of .bind, which is known to be slow currently.
Is the call to bind() itself slow, or calling a function after it has been bound makes it execute slower? The former would not matter, since I am calling bind() before starting the timer. The latter (which I think I have observed in the past) would indeed skew the results if true.

It's both. You could of course try to counter-balance that by also (redundantly) applying .bind to goog.Promise. :)


On 7 August 2015 at 09:33, Andreas Rossberg <ross...@google.com> wrote:
On 7 August 2015 at 01:45, <dpa...@chromium.org> wrote:
I was comparing native Promise performance with goog.Promise (from https://closure-library.googlecode.com/git-history/docs/local_closure_goog_promise_promise.js.source.html).
I was surprised that the JS version is much faster, example snippets below.

This is a known problem. Several reasons:

1. V8 promises haven't been optimised at all. It's on our agenda once our ES6 support is feature complete.
2. V8 promises support various callback hooks into devtools, which cause a certain overhead.
3. Alternative promise implementations tend to take shortcuts relative to the official ES6 semantics (e.g., goog.Promise.all you use below does not support subclassing correctly).

We assume that (1) is the main factor, and will go away eventually, but due to the others some (hopefully minor) differences might remain.

Also, add the usual caveat about micro benchmarks. Does this measurably affect real applications?
I believe it does. Have not proved it yet, but it's easy. I will replace goog.Promise with Promise in some of Lovefield's code (https://github.com/google/lovefield) which makes heavy use of goog.Promise and come back with an answer to this.

Cool, thanks. That would be useful data for us.
Reply all
Reply to author
Forward
0 new messages