-
-
Notifications
You must be signed in to change notification settings - Fork 208
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
possible performance impact when updating from v4.2.0 to v5.0.0 #506
Comments
@adrai Hi, thank you for your report. In the commit, you mentioned we changed the way of resolving schema references because the former way to do it hasn't covered all use cases. We saw that it has some performance downgrade on cold start (reference resolving happens only in compile time), but it wasn't so dramatical #462 (comment). If you can provide some details on a case where performance dropped from 400ms to 1600ms, it might help. |
Just created an example repo... https://github.com/adrai/fastify-slower-schema-resolving |
You have a lot of schemas loaded indeed. |
And in reality there are even more 😉 |
Are there any unit tests breaking when we use refFinder instead of ajv.getSchema? |
Yes, there were actually a few attempts to fix them, but it was complicated, so we ended up using Ajv for it. |
I'm working on the standalone feature because I belive this is the best approach on the long run and it was a while since I had this in mind (moreover this should be the fastest solution with tangible results). |
Doesnt ajv use internally a weakmap? |
@Eomm The other way to speed up it is to reuse context schemas. Now fast-json-schema-compiler binds context schemas and passes them to the FJS whenever it needs to build a new serializer. What we can do is pass schemas to FJS, clone and modify them only once, and then reuse them. It would be also great to figure out how to reuse one Ajv instance, but I don't have the answer now. |
Before any action, I would focus on:
If the user adds all the schema in the same context, only one serializer will be built, so this optimization is already doable by the user. |
A user can add schemas globally, and MIGHT has references on them, but it's not necessary. When we compile a route's serializer, we clone these schemas and build a new Ajv instance even if you don't have a reference on them. So if you have a lot of schemas in one namespace (added by fastify.addSchema), it might cause a performance downgrade (It is better to test it). We can think about how to reuse context schemas or maybe compile them in a lasy way. |
I've already tried to check this, here some numbers: https://github.com/adrai/fastify-slower-schema-resolving/tree/main/simple-benchmarks |
Holy moly, I forgot it: we are processing We could:
|
@Eomm The problem is how to add the route schema (non-external), compile a serializer, and then remove it from Ajv. Because routes schemas should be isolated from each other. By the way, it looks like we have another problem here. Ajv compiles a validation function when we are calling getSchema. |
I found the problem. Ajv compiles a validate function at the first interaction with the schema. When we call the getSchema, it will compile a validation function even if it's not necessary. If we replace here the last line to return { schema: sch.schema } the performance would still be great. We can try to add an optional parameter to the Ajv.getSchema that will not force to compile the validation function, but I think it will not work. |
Maybe it is an upstream issue that @epoberezkin should know of. |
I assume it's not an issue at all. It's by design that getSchema returns compiled schema. It's our problem that we don't need it in some cases. |
Prerequisites
Issue
Hi!
Today I was doing some dependency updates for my fastify apps, when I noticed a bigger InitDuration for my AWS Lambdas.
To have an idea my await app.ready() call went from approx. 400ms to approx. 1600ms (on AWS Lambda this went up to 18000ms and also caused some timeouts) by updating from fastify v4.1.0 to v4.2.0.
After some testing I'm assuming that probably fast-json-stringify is causing this because of this commit.
I'm not so familiar with the internals, but this simple test, helped me to compare a bit more.
For example by wrapping the
refFinder(schema.$ref, location)
call here: https://github.com/fastify/fast-json-stringify/blob/v4.2.0/index.js#L108 in v4.2.0i.e. like this:
I basically get always 0 ms for the time measurements for all invocations, but compared to the newer
ajvInstance.getSchema(schemaRef)
call here: https://github.com/fastify/fast-json-stringify/blob/v5.0.0/index.js#L64 in v5.0.0i.e. like this:
I'm now getting 2-20ms for the time measurements for the different invocations.
Like said, I'm not familiar with these internals, but I assume ajv.getSchema is getting the fastify.ready() call much slower.
I'm sorry for my unprofessional reproduction steps, but I hope this information may help to understand the issue.
The text was updated successfully, but these errors were encountered: