Skip to content
This repository has been archived by the owner on Dec 14, 2022. It is now read-only.

Avoid the generic promisify. #2

Merged
merged 1 commit into from
Oct 11, 2018
Merged

Avoid the generic promisify. #2

merged 1 commit into from
Oct 11, 2018

Conversation

bmeurer
Copy link
Member

@bmeurer bmeurer commented Oct 11, 2018

The doxbee and parallel benchmarks were using a generic promisify
implementation to wrap dummy functions with callbacks into promisified
functions that can be used with Promise/async code. This promisify
implementation doesn't match the implementation in Node.js, which is
not portable across engines (and somewhat coupled to Node.js internals).

However with the recent performance improvements the doxbee benchmark
is not dominated by this generic promisify, which means it doesn't
really measure Promise performance improvements anymore. So to make
sure the benchmarks are still meaningful we change them and manually
promisfy the dummy functions instead.

This will create a new baseline for the performance, but it'll make
sure that the benchmarks stay relevant.

The doxbee and parallel benchmarks were using a generic promisify
implementation to wrap dummy functions with callbacks into promisified
functions that can be used with Promise/async code. This promisify
implementation doesn't match the implementation in Node.js, which is
not portable across engines (and somewhat coupled to Node.js internals).

However with the recent performance improvements the doxbee benchmark
is not dominated by this generic promisify, which means it doesn't
really measure Promise performance improvements anymore. So to make
sure the benchmarks are still meaningful we change them and manually
promisfy the dummy functions instead.

This will create a new baseline for the performance, but it'll make
sure that the benchmarks stay relevant.
@bmeurer bmeurer merged commit 422f733 into v8:master Oct 11, 2018
function dummy_1() { return Promise.resolve(undefined); }
function dummy_2(a) { return Promise.resolve(undefined); }

// a queryish object with all kinds of functions

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you describe what "queryish" means or what it's supposed to mock?

@benjamingr
Copy link

Wait, why? Node.js changed promisify to use the same implementation a few months ago.

@bmeurer
Copy link
Member Author

bmeurer commented Oct 11, 2018

@benjamingr Meh, I was staring at the wrong checkout 🙁

I was already puzzled that it was still using the V8 internal APIs since we had a discussion to not do that anymore. Was there any visible performance impact when using this generic promisify?

@bmeurer
Copy link
Member Author

bmeurer commented Oct 11, 2018

@benjamingr Didn't we conclude in Berlin that Node.js should use the createPromise API that is exposed via v8-extras? Sorry, it seems that I somehow forgot all of this 🤔

@bmeurer bmeurer deleted the promisify branch October 11, 2018 12:01
@benjamingr
Copy link

I was already puzzled that it was still using the V8 internal APIs since we had a discussion to not do that anymore. Was there any visible performance impact when using this generic promisify?

There was not - which was surprising at the time. You reviewed the changes 😅

Didn't we conclude in Berlin that Node.js should use the createPromise API that is exposed via v8-extras? Sorry, it seems that I somehow forgot all of this 🤔

We did, but I don't think anyone actually ended up doing it. I'd like to call a meeting of the promises-debugging group after all the people who are in JSI and the Vancouver summit are back to get a better understanding of what works, what doesn't, where we are and how to move forward.

@bmeurer
Copy link
Member Author

bmeurer commented Oct 11, 2018

@benjamingr Yeah, just went through that part of history. And I think it was the performance numbers that convinced me. Ok, so that makes a lot of sense...

As far as these benchmarks here are concerned, we need to keep them useful, and right now they are turning into spread call benchmarks with 20-25% of the execution time just going into the promisify wrapped function, which makes the benchmarks less relevant to actual async/promise performance.

We'll have to optimize spread calls, for sure, but that'll have its own proper benchmark.

@benjamingr
Copy link

We'll have to optimize spread calls, for sure, but that'll have its own proper benchmark.

If the spread call is taking 20%-25% of the execution time maybe we need to remove that spread call from Node? Is there a faster alternative (other than v8-extras which means other baggage in Node core)

@bmeurer
Copy link
Member Author

bmeurer commented Oct 11, 2018

It's not only the spread call, but also the fact that due to some other limitations, the args gets context allocated when passing it the executor function, which later in the optimization stages gets relaxed, but the early inlining optimizations will be blocked by that. This combined led to the fact that promisify is starting to dominate these microbenchmarks.

I'm not sure what the impact is on bigger applications. The only alternative I see is to use v8-extras, which should probably be faster.

@benjamingr
Copy link

Interesting, we've found promisify to dominate a lot of the benchmarks in the past as well - but we've also found it to be the case in real applications.

These tests were in ~2013 and I'm not sure if it's the case anymore.

@bmeurer
Copy link
Member Author

bmeurer commented Oct 11, 2018

Interesting. So the Promise constructor approach that you're shipping now is at least as efficient as using the special C++ promise methods that you exposed previously, which makes sense. Now utilizing v8-extras instead might given an extra promisify performance boost; it should be tried at least.

@benjamingr
Copy link

Interesting. So the Promise constructor approach that you're shipping now is at least as efficient as using the special C++ promise methods that you exposed previously, which makes sense.

Right, and I believe the overhead of calling promisified functions is still significant in real world apps though that assertion needs to be re-validated.

Now utilizing v8-extras instead might given an extra promisify performance boost; it should be tried at least.

What would be the best way to approach this? It seems like there is a lot of background I am not familiar with in adding v8-extras to node.

@bmeurer
Copy link
Member Author

bmeurer commented Oct 12, 2018

I don't know what's the best way to add it. The code for promisify itself would look pretty much the same as you had before. I guess @hashseed can speak to the integraiton bit.

@hashseed
Copy link
Member

V8 extras functionality is exposed via the extras bindings object. @jasnell probably knows more about how node accesses that.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants