You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current implementation of isObject from @rjsf/utils is guaranteed to access at least one of the File and Date native classes for instanceof checking. This incurs significant latency in the specific scenario where the a qiankun sub-application rerenders a Form component due to the combination of factors:
High amount of isObject calls that each access File and Date classes
Small overhead incurred each time File or Date is accessed due to qiankun's proxy sandbox.
For more context on how I discovered this issue, read the "Background" section
Expected Behavior
isObject should be able to return early when it knows that the value cannot be a File or Date, which would greatly reduce the occasions that File and Date are accessed to only the times where objects that resemble a File or Date are passed into isObject.
I've been exploring optimizing isObject in this regard via this fork of RJSF.
Steps To Reproduce
Creating a sandbox example using RJSF within a qiankun sub-application is quite nontrivial, so for now, here's a playground demonstrating the number of accesses to File and Date made when updating a Form component: https://codesandbox.io/p/sandbox/react-jsonschema-form-forked-p3nspn
Click on 'LoadData', which populates the Form component with new data
Notice how several hundred accesses to File and Date are made on the spot despite the data having no Files or Dates to speak of
Try modifying the form data before pressing 'LoadData' again
Note how the number of accesses to File and Date increased by a larger amount than before
The product I help develop uses the micro-frontend framework qiankun to run a React application providing multiple independent React sub-applications. To enforce isolation of these sub-application, qiankun provides proxy sandboxes that intercept accesses to globalThis, window, and other similar objects from the sub-applications.
When using a Form component with large schema within one sub-application, I quickly noticed that it took several hundred milliseconds overall for the UI to update after each letter typed, and so I started profiling performance via Chrome DevTools to investigate further.
Two primarily sources of overhead discovered are:
Inefficient layout updates - my team is currently working to optimize this
Rerendering of the Form component
Taking a deeper look at the second cause of overhead reveals a significant amount of self time coming from specific functions with RJSF and qiankun:
A significant portion of the total time of the Form rerendering task is devoted to isObject from @rjsf/utils, which at first glance should be trivial to evaluate and have no impact on performance whatsoever. Diving deeper into the performance timeline reveals where the overhead comes from:
As it turns out, the "proxy sandbox" mentioned above intercepts accesses to any property of globalThis, including File and Date, and the proxy's functions incur a small overhead (usually 0.15ms~0.5ms) each time such properties are accessed. This small overhead adds up very fast given the number of times isObject is called whenever the Form component updates.
The text was updated successfully, but these errors were encountered:
@Hsifnus Wow, great analysis. If you believe that your optimization will not cause any regressions, we welcome PR. Please make sure to maintain 100% unit test coverage in the @rjsf/utils package. Thanks
Prerequisites
What theme are you using?
utils
Version
5.18.2
Current Behavior
The current implementation of
isObject
from@rjsf/utils
is guaranteed to access at least one of theFile
andDate
native classes forinstanceof
checking. This incurs significant latency in the specific scenario where the a qiankun sub-application rerenders a Form component due to the combination of factors:isObject
calls that each accessFile
andDate
classesFile
orDate
is accessed due to qiankun's proxy sandbox.For more context on how I discovered this issue, read the "Background" section
Expected Behavior
isObject
should be able to return early when it knows that the value cannot be aFile
orDate
, which would greatly reduce the occasions thatFile
andDate
are accessed to only the times where objects that resemble aFile
orDate
are passed intoisObject
.I've been exploring optimizing
isObject
in this regard via this fork of RJSF.Steps To Reproduce
Creating a sandbox example using RJSF within a qiankun sub-application is quite nontrivial, so for now, here's a playground demonstrating the number of accesses to
File
andDate
made when updating a Form component: https://codesandbox.io/p/sandbox/react-jsonschema-form-forked-p3nspnForm
component with new dataFile
andDate
are made on the spot despite the data having noFile
s orDate
s to speak ofFile
andDate
increased by a larger amount than beforeEnvironment
Anything else?
Background
The product I help develop uses the micro-frontend framework qiankun to run a React application providing multiple independent React sub-applications. To enforce isolation of these sub-application, qiankun provides proxy sandboxes that intercept accesses to
globalThis
,window
, and other similar objects from the sub-applications.When using a Form component with large schema within one sub-application, I quickly noticed that it took several hundred milliseconds overall for the UI to update after each letter typed, and so I started profiling performance via Chrome DevTools to investigate further.
Two primarily sources of overhead discovered are:
Taking a deeper look at the second cause of overhead reveals a significant amount of self time coming from specific functions with RJSF and qiankun:
A significant portion of the total time of the Form rerendering task is devoted to isObject from
@rjsf/utils
, which at first glance should be trivial to evaluate and have no impact on performance whatsoever. Diving deeper into the performance timeline reveals where the overhead comes from:As it turns out, the "proxy sandbox" mentioned above intercepts accesses to any property of
globalThis
, includingFile
andDate
, and the proxy's functions incur a small overhead (usually 0.15ms~0.5ms) each time such properties are accessed. This small overhead adds up very fast given the number of timesisObject
is called whenever the Form component updates.The text was updated successfully, but these errors were encountered: