-
-
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
Tracking issue: Performance improvement #73
Comments
Thanks for your research and the benchmark suite. This week I will focus exclusively on performance for a few days and probably release a new version with performance improvements. @BastiDood had recently checked the performance of |
I expect to start my performance research on Wednesday or Thursday and then share my findings with you here. I plan to test the validation for the success and failure case under normal and extreme conditions between different libraries. For Valibot, the most important thing is to find the vulnerabilities in the code that are currently affecting performance. Thank you @naruaway for the vulnerabilities you have already found. |
Hi @fabian-hiller, I updated (actually, a lot :) ) https://github.com/naruaway/valibot-benchmarks and now it can easily compare different versions of Valibot as well, not only Zod, for example, here is the excerpt of the performance of #46 🎉 : Also, I confirmed that in my MacBook, after my changes Valibot is faster than Zod except for "failure" data. I plan to set up GitHub actions to run it also in Linux and Windows. If you have a chance, could you check out the README of https://github.com/naruaway/valibot-benchmarks ? Also if you have additional test cases, it might be nice to manage in the same place. All the schema and data put in https://github.com/naruaway/valibot-benchmarks/tree/main/test_data are automatically picked up by the benchmarker. My next plan is to finish up my PRs with evidences using this tool. And then I'll also run the benchmark against recently merged PRs to detect potential regressions. Note that this tool can also generate bundle size for each schema since each test case is bundled separately first by webpack |
Thank you very much. I have clicked through a bit. Great work! I think it's great that your suite automatically takes into account different run times. The idea is cool to run benchmarks on PRs as well to notice the impact of changes. Maybe in the long run we'll also integrate some benchmarks into the website. |
I just want to let you know that I will probably not be able to start my performance research until the weekend, because I am currently looking at Zod, ArkType and Typia as part of my bachelor thesis. |
Vitest has builtin benchmarking method (link) but it's still experimental (btw type testing is experimental too, but it already used in valibot). Can we use this method to unify perfomance testing for beginners? To start, we could copy tests from typescript-runtime-type-benchmarks to compare perfomance with zod in pull requests. This also allows to use benchmarking in ci as well as testing and unify running platform's cpu and arch. I'm afraid this leads to adding zod and other libs into |
Oh Vitest's benchmarking is interesting! FYI I am prototyping my benchmark suite to make sure it's potentially more precise (e.g. it's bundling each lib using webpack production mode with minifier and each run is launching specific engine every time separately (e.g. Node.js/Bun/Deno/want to add quickjs-wasm)) and also tests extreme cases (e.g. this case is useful to reveal the slowdown effect of throwing errors since try-catch happens many times for "wide" schema) Anyway I think we can integrate simpler benchmark suite (Vite benchmark seems to be good choice!) in the main valibot repo to prevent obvious regressions |
Yeah, I was exploring your suite and my first thought was it's quite difficult to use for pull requests without publishing to npm, or you need to copy the lib before and after changes manually. I think your work is most suitable to valibot website for visual demonstration, because github markdown doesn't have bar charts. Also I don't know if vitest supports different engines as deno and bun.
|
@fabian-hiller, If you don't mind the vitest benchmark and including it in github workflow, I can make a pr. |
Yes, feel free to make a draft PR |
Two small thoughts, although I did not benchmark anything yet:
|
When I implemented the refactor from
I think this is a worthwhile exploration. I'd be quite surprised if the JIT compiler doesn't already apply this optimization over time. Nevertheless, the However, this is less relevant when Valibot is already bundled into a single file. Modern bundlers are quite aggressive with inlining and hoisting imports, which makes the aforementioned issues with globality a non-issue. I'd be interested to know if the three-condition version would be better than the bundled version anyway. |
We have now reworked the entire library to optimize performance. The changes are in the Feel free to test your ideas with the code in the |
@fabian-hiller After ArkType's alpha release, I wanted to spend some time learning about the performance characteristics of other validators. ArkType was similar to Zod at that point, both of which I think took a reasonably performant approach, yet somehow according to the benchmarks validators like Typia and Typebox were hundreds of times faster. Any discussion of validator performance should centrally address the one aspect of the implementation that accounts for the vast majority of that difference- whether the validator precompiles its constraints. During the build process or at runtime via the Because of those advantages, ArkType's upcoming release is precompiled by default via the Function constructor and will offer a precompilation process that can be integrated with the build (also offers a path toward optimal bundle size). However, though being 400x faster than Zod sounds impressive, for the vast majority of use cases, whether validation takes a compile microseconds or a couple nanoseconds really won't matter. I think incremental steps like this to improve performance are valuable, but hopefully it's helpful to know that if having highly-optimized performance is a top priority, finding a way to leverage V8's JIT optimizations makes everything else look like a rounding error. Great work again on Valibot. If you have any questions about ArkType or the ecosystem in general, I'm happy to talk anytime 😊 |
Hi @ssalbdivad, thank you for your message. I would be happy to exchange ideas. Feel free to add me, I also looked at other solutions like Typia, and it is true that a compiler can generate code that a "normal" library can't match. However, the compilation step also brings disadvantages. My goal for Valibot is to find a good compromise between API design, bundle size, and performance. As soon as that is done, we will see further. |
Yes! Sorry if it wasn't clear, my comment wasn't meant to say this is what Valibot should do. If anything, I'd say that outside of the marketing value, optimizing validation performance beyond the basics is rarely a good investment. Just wanted to make sure you were aware of this and not comparing the current performance to solutions that do something totally different👍 |
Edit: looks like I forked this repo before you changed your approach to error handling. Hah! Hey, not sure what the approach for the upcoming versions is going to be, but I have an experimental branch that seems to improve Valibot's performance quite a bit compared to 0.12:
The basic idea is not to throw errors but return a discriminated union of Unfortunately I'm just about to go on a holiday trip so won't be able to continue this for a while, but this might be an interesting approach to pursue. I got this idea since similar performance work was done by @milankinen on Zod a good while ago I also haven't yet had time to validate that the validators are actually doing what they're supposed to be doing, since all the tests are broken |
DX of |
Thanks @jussisaurio for your research. Yes, I implemented almost the same thing yesterday. For v0.13.0, the goal is maximum performance, and for v0.14.0, to reduce the bundle size and make the code prettier. So I am happy to get more feedback. |
@naruaway can you check in your benchmark suite if it makes a difference to write Example with current for loop implementation: valibot/library/src/schemas/object/object.ts Lines 142 to 144 in db27144
|
@fabian-hiller Sure, I ran the benchmark suite for the following commits on my MacBook Air (M2 chip):
Benchmark results
In the above result, we see the following:
|
Thank you for the data! I will think about it. |
Valibot v0.13.0 with extreme performance improvements is now available! Thank you for your contributions! |
This is a tracking issue to discuss & improve the performance of Valibot.
I created a benchmark suite for Valibot so that we can track its runtime performance in many situations since existing benchmarks were failing to capture the real world schema and data diversity.
The current latest result can be checked from https://naruaway.github.io/valibot-benchmarks/
Currently we see the following interesting observations:
I'll continue improving my benchmark suite and will post any interesting information here.
We already have several performance improvement PRs: https://github.com/fabian-hiller/valibot/pulls?q=is%3Apr+is%3Aopen+label%3Aperformance
I'll post benchmark result for each PR later
The text was updated successfully, but these errors were encountered: