Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: sync resolvers #3504

Draft
wants to merge 2 commits into
base: dove
Choose a base branch
from

Conversation

DaddyWarbucks
Copy link
Member

See: #3492

This PR is a WIP and a proof of concept. I have added a new _resolve method and added a test to compare the speed of this method compared to the current resolve method. The new _resolve method does not use Promise.all to resolve properties. Instead, it uses a basic for loop and done callback. This ensures resolvers that are not actually promises are not scheduled on the event loop.

When running the tests for the package you will see some console.time results. I purposefully left the test configure in a manner that favored syncResolvers. This should accurately illustrate the problem with assuming all resolvers are promises. But you can configure these settings however you would like.

const count = 10000
const asyncResolvers = 1
const syncResolvers = 10
const runs = 10

sync0: 86.879ms
sync1: 72.509ms
sync2: 171.684ms
sync3: 69.843ms
sync4: 67.955ms
sync5: 77.137ms
sync6: 75.034ms
sync7: 79.12ms
sync8: 77.653ms
sync9: 78.587ms

async0: 180.141ms
async1: 173.855ms
async2: 169.611ms
async3: 168.678ms
async4: 162.778ms
async5: 177.389ms
async6: 193.163ms
async7: 316.745ms
async8: 157.414ms
async9: 163.333ms

Interestingly, even when using all asyncResolvers the _resolve method is faster. I have noticed this when writing similar updates for yupjs and feathers-fletching. I speculate its because the callback pattern can pop promises off the loop as it goes and Promise.all has to keep them all in the loop until they are done? Pure speculation.

const count = 10000
const asyncResolvers = 10
const syncResolvers = 0
const runs = 10

sync0: 258.305ms
sync1: 124.654ms
sync2: 123.168ms
sync3: 128.291ms
sync4: 126.634ms
sync5: 126.913ms
sync6: 131.84ms
sync7: 134.369ms
sync8: 125.799ms
sync9: 128.844ms

async0: 159.942ms
async1: 167.286ms
async2: 156.082ms
async3: 156.891ms
async4: 321.241ms
async5: 177.017ms
async6: 160.917ms
async7: 155.687ms
async8: 149.171ms
async9: 146.085ms

The _resolve method passes all tests but one. You can rename it to resolve (comment/rename real resolve method). It fails one test around virtuals. I played with it and couldn't get it, but I am confident its solvable.

I am also curious if feathersjs/hooks could benefit from a similar treatment. I am not sure how it would work with the next-able hooks, but that may even make it easier. This would allow entire Feathers applications to get a performance boost if hooks like disallow, etc aren't consuming the event loop.

@DaddyWarbucks DaddyWarbucks changed the title Feature/sync resolvers Feature: sync-resolvers Jun 22, 2024
@DaddyWarbucks DaddyWarbucks changed the title Feature: sync-resolvers Feature: sync resolvers Jun 22, 2024
@DaddyWarbucks DaddyWarbucks requested a review from daffl July 12, 2024 15:58
@DaddyWarbucks DaddyWarbucks marked this pull request as draft July 12, 2024 15:58
@DaddyWarbucks
Copy link
Member Author

I know this needs to fix one test before its actually ready. But I wanted to get @daffl and @marshallswain eyes on it for some feedback. Ya'll let me know any thoughts/questions/concerns.

@daffl
Copy link
Member

daffl commented Jul 15, 2024

Thank you for putting this up. It's kind of interesting that things like this don't seem to get optimized by V8.

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

Successfully merging this pull request may close these issues.

2 participants