NumericInput causing significant performance drops in Firefox
#5466 opened on Jul 26, 2022
Description
Environment
- Package version(s): 4.6.1
- Operating System: Tested on Windows 10
- Browser name and version: Firefox 102
Code Sandbox
https://codepen.io/PurkkaKoodari/pen/mdxMNKb
The demo renders two forms: A contains 100 NumericInputs with constant values and a Slider, B is the same but with InputGroups. All props to the NumericInputs are literal constants. (Using 100 inputs just to exaggerate the effect, but it's noticeable even in much smaller forms.)
Steps to reproduce
- Open the demo in Firefox (seems to be less of an issue in Chrome).
- Drag the sliders around quickly.
Actual behavior
In Firefox, the form (and slider) with NumericInputs renders very slowly.
Expected behavior
Both sliders should move smoothly.
Cause
Looking at the Firefox profiler, the issue seems to be that React is still calling NumericInput.getDerivedStateFromProps even when props don't change. That calls Number.prototype.toLocaleString numerous times, which seems to be super slow on Firefox:

In our own app, NumericInput rendering takes up ~15% of CPU time when a form containing any NumericInputs is re-rendered. This time isn't visible at all in the React profiler, as the component's aren't rendering - I believe the time is counted against the parent components instead!
Possible solution
Since getDerivedStateFromProps doesn't use sanitizedValue unless min or max are changed, moving its computation inside if (didBoundsChange) should be a trivial improvement:
Furthermore, most of the time is spent in isFloatingPointNumericCharacter. One could probably cache the decimal regexes per-locale for a decent perf boost. (Currently, it's re-computing the regex for each character of the input string.)
I'm happy to write a PR if you agree with the suggestions.