rjsf-team / react-jsonschema-form

A React component for building Web forms from JSON Schema.
https://rjsf-team.github.io/react-jsonschema-form/
Apache License 2.0
14.33k stars 2.19k forks source link

Performance problems with allOf #4051

Open magaton opened 9 months ago

magaton commented 9 months ago

Prerequisites

What theme are you using?

mui

Version

5.16.1

Current Behavior

When using allOf subschemas are validated multiple times for each render, no matter if the controlling field (where allOf is placed) has been changed or not. This results in many. in the complete version, hundreds of unnecessary calls of isValid() in validator.ts.

Moreover, in validator.ts, if I remove the comment from this line, the caching of rootSchema is enabled. This helps a bit since rootSchema is not validated for each render, but subschemas are validated, although compiled only once (initially) since their compiled validator is found in the cache.

I have tried to figure out what is causing this. I have looked in MultischemaField, but could not understand why subschemas are validated for each render, multiple times. Also, I have tried to add a discriminator, hoping that this would skip calling isValid, but no luck, since my controlling fields are usually arrays and allOf is using contains.

My battle with performance is really a long one:

but this time, I think I was able to identify the problem.

It is not a compile problem, compilers are cashed by generated hash, but numerous isValid calls.

Could you please help, at least by pointing out what is causing this and what could be the solution for this problem, so that, at least, users can use my application? Now it is terribly slow and laggy on each keystroke.

Thanks in advance.

Expected Behavior

I would expect that isValid is called only once per each render, if and only if the controlling field value has been changed.

Steps To Reproduce

Please check the repo demonstrating this problem. You will be able to see numerous isValid calls for each subschema in every allOf, no matter whether it is an initial render or change in a completely irrelevant field.

Environment

- OS: mac osx
- Node: latest
- npm: latest

Anything else?

No response

magaton commented 9 months ago

Could this be a reason?

heath-freenome commented 9 months ago

@magaton the isValid() has to be called once per condition per render. And it may likely be done more than necessary. I wish I had the time to dig into this. There are so many things that I wish were implemented/fixed. Unfortunately we are only volunteers. How can we help you fix this for yourself?

magaton commented 9 months ago

@heath-freenome, thanks for the answer. What would be the idea behind validating allOf conditions every time on each render, no matter what property has been changed? I would expect that only if the property that drives allOf conditions changed, the allOf conditions are validated. I think this is how oneOf and anyOf work. Can you confirm that?

It would be very helpful if you could tell me what I need to change locally to eliminate those excessive isValid calls for all allOfsubschemas.

Thanks

magaton commented 9 months ago

@heath-freenome I have realized it is not about allOf but if-then-else, either standalone or inside allOf. if-the-else is validated every time, instead ONLY if the controlling field changed its value. I am wondering whether it would be possible to add this feature. At this point, the only way how I was able to bypass the extensive validation of all (100s) of conditionals in the schema was to set helper fields on the form onChange event which I put inside the dependencies section. No need to say that I ended up with huge number of them + super complicated onChange handler.

heath-freenome commented 9 months ago

@magaton Feel free to come to the RJSF meeting today at 12pm PST to talk about this

heath-freenome commented 9 months ago

@magaton or we could chat one-on-one via Discord.