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

Performance problem #116

Open
manwithsteelnerves opened this issue Apr 14, 2020 · 35 comments
Open

Performance problem #116

manwithsteelnerves opened this issue Apr 14, 2020 · 35 comments

Comments

@manwithsteelnerves
Copy link

Currently it's taking around 1.2 seconds to load the module. Any way to get better loading times?

Screenshot 2020-04-15 at 3 21 53 AM

@kibertoad
Copy link
Collaborator

kibertoad commented Apr 14, 2020

Wonder what takes so long. Which Node version are you using? About the only type of logic executed on import that is not import that I see is this:

if (!Object.values) {
    values.shim();
}

object.values shim itself is also already executing some launch on import, so that makes it a culprit.

update: looks like main reason is old verison of swagger-parser that brought core-js with it

@kibertoad
Copy link
Collaborator

https://github.com/PayU/api-schema-builder/pull/45/files removes dependency on core-js, so I think that would help.

@manwithsteelnerves
Copy link
Author

I'm on Node 8 + firebase functions setup.

@manwithsteelnerves
Copy link
Author

And also will be waiting for the update to get approved. Can't wait to test it :)

@kibertoad
Copy link
Collaborator

@manwithsteelnerves Could you try version from #121 and see if it makes any difference?

@kibertoad
Copy link
Collaborator

Released in 3.0.0
@manwithsteelnerves Can you profile the new version and check the difference?

@manwithsteelnerves
Copy link
Author

I used 3.0 and see the performance not better than previous but unfortunately, bad.
I will do more tests, but meanwhile please check the trace screenshot. It took 4secs to load.
Screenshot 2020-05-14 at 2 22 25 PM

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented May 14, 2020

Also, in the above test, I was just referring InputValidationError type alone. Anyway to refer that type(for type info) alone and not load the complete module?

@manwithsteelnerves
Copy link
Author

Here are few more tests where it took 1.87secs which I see is more consistent after several tests.
If there is a way to switch off v3 spec check, it would be great as we can squeeze some performance. Currently we are using swagger v2 but its still loading v3 which accounts for 700+ms.
Please suggest.

Screenshot 2020-05-14 at 4 42 56 PM
Screenshot 2020-05-14 at 4 42 46 PM
Screenshot 2020-05-14 at 4 43 06 PM

@kibertoad
Copy link
Collaborator

Should be possible to short-circuit that. Will investigate. I'm curious, what is your use-case? Why optimize for startup speed?

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented May 14, 2020

I'm using it in server-less functions. To be specific, Firebase cloud functions. Unfortunately there is no idle time defined for instances which spin up. This makes it a requirement that the loading needs to be faster as loading of the module will be nearly happening on every request.

@kobik
Copy link
Collaborator

kobik commented May 15, 2020

@manwithsteelnerves , can you share your definition file?

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented May 15, 2020

Here is the schema.

@manwithsteelnerves
Copy link
Author

@kobik Do you see anything wrong with the spec?

@kobik
Copy link
Collaborator

kobik commented May 16, 2020

I'll have a look tomorrow

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented May 19, 2020

@kobik If I split the json, will it be of any help?

Edit : I'm trying to split the spec into multiple so that there will be one file per route. Is it possible to pass to init the main spec file and refer its model definitions from another file?

@kobik
Copy link
Collaborator

kobik commented Jun 24, 2020

Hi @manwithsteelnerves , i'm very sorry for the late response.

I'm on it now.

@kobik
Copy link
Collaborator

kobik commented Jun 24, 2020

according to my measurements:

  • require dependencies ~150-170ms
  • dereferencing: ~50-60ms
  • building validations: ~560-600ms
    building validations per api takes between ~16-90ms, while most of the time is spent on building the response validation. i'll continue investigation and break the fixes into several PRs.

@kobik
Copy link
Collaborator

kobik commented Jun 25, 2020

@manwithsteelnerves would you mind testing the beta version?

i did some optimizations of the require statements and i'd like see if it's making things better for you.

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented Jun 25, 2020

Sure! Happy to do that :)
Please let me know the steps in brief. I will arrange for the test.

Just to let you know, I made the bulk single schema to multiple parts(as per enpoint+http method). But still I find it taking some time. so I can get you those values.

@kobik
Copy link
Collaborator

kobik commented Jun 25, 2020

So your actual schemas are much smaller? Can you share an example of a real schema you're using?

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented Jul 2, 2020

Sorry! I missed your comment!

Yes, the schema size now is per endpoint and I will be loading at runtime every time the endpoint is triggered.
I understand it will have the overload on every execution now but the cold starts doesn't have a long delay. There is a tradeoff.
If its possible to reduce the overload of the module entirely, it will definitely help however. Let me profile the latest one.

Please check the schema here.

If overall performance ramps up, definitely I revert my code to old single schema approach as its one time load.

@manwithsteelnerves
Copy link
Author

@kobik May I know how to download the latest version to profile?

@kibertoad
Copy link
Collaborator

@manwithsteelnerves Judging by what I see on npm, I believe 3.0.0-beta.0 is it.

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented Jul 2, 2020

I saw it but wanted a confirmation. Let me try that!
Edit: Also, I don't see any recent commits in all tags/branches. Am I missing something? Last commits are 2 months ago. Can you please share the code change to look into?

@kibertoad
Copy link
Collaborator

@manwithsteelnerves
Copy link
Author

manwithsteelnerves commented Jul 2, 2020

Hi,
Here are the details.
I reverted to single schema as I see it better as on every endpoint loading I see nearly 300ms of processing time and it can't be cached as the same endpoint won't be hit in the same cloud function instance, very unlikely. So, handling one time per function instance is optimal as it can be cached in memory. Just that I need to find ways to reduce the loading time of it.

So I have the old setup only to continue our comparisons.
I see it took around 1.44 secs to load the schema. I need to inform that compared to earlier as its 20% reduction.

But, incase if you see anyways I can reduce it further, please let me know. This is because, on serverless platforms this is crucial.

I'm attaching the screenshot as well as the trace file which you load it using this tool. Please check from 2.7secs.

Also, I'm using this type which is adding nearly 500ms just for the type alone.
Screenshot 2020-07-02 at 9 20 12 PM

import { InputValidationError } from 'openapi-validator-middleware';

It would be great if you let me know i'm doing anything wrong.

Trace

Screenshot 2020-07-02 at 10 22 21 PM

@kobik
Copy link
Collaborator

kobik commented Sep 2, 2020

@manwithsteelnerves , i'm not sure what else we do here.

Can you try using initAsync instead of init and report with your findings?

@kobik
Copy link
Collaborator

kobik commented Sep 2, 2020

I actually had another idea I've toyed with in my mind, which is caching of the validation object.

allow to create from a definitions file and export the validation object to a file.

then init the middileware by giving it the exported validation object file.

do you thing it would be an acceptable solution?

@manwithsteelnerves
Copy link
Author

I actually had another idea I've toyed with in my mind, which is caching of the validation object.

allow to create from a definitions file and export the validation object to a file.

then init the middileware by giving it the exported validation object file.

do you thing it would be an acceptable solution?

Just to be on the same page, can you share more details about it?
Is it like an intermediate format which extracts the required data from schema and have it in compact format?

@kobik
Copy link
Collaborator

kobik commented Sep 3, 2020

It's like creating and committing a "compiled" version of the definitions file and use it instead of the definitions file for a faster loading times.

This is just an idea that we need to see if it's even a feasible plan.

But first I'd like to hear what you think of this idea and second I'd still appreciate if you'd test the asyncInit.

Thanks

@manwithsteelnerves
Copy link
Author

Thats a nice one. Most likely it can give better performance.
asyncInit I see it may not be useful for me as I need to have the initialization ready before servicing any requests.

@manwithsteelnerves
Copy link
Author

@kobik Did you make any performance progress post this? I don't see the release notes to go through, so check if any updates you have.

@manwithsteelnerves
Copy link
Author

@kobik Would love to know if any thing you have progressed on this.

@kibertoad
Copy link
Collaborator

@manwithsteelnerves Some of the heavier dependencies were dropped, so that would speed up at least the import part. I don't think schema loading changed much since then.

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

No branches or pull requests

3 participants