Skip to content
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

NumericInput causing significant performance drops in Firefox #5466

Open
PurkkaKoodari opened this issue Jul 26, 2022 · 1 comment · May be fixed by #7178
Open

NumericInput causing significant performance drops in Firefox #5466

PurkkaKoodari opened this issue Jul 26, 2022 · 1 comment · May be fixed by #7178

Comments

@PurkkaKoodari
Copy link
Contributor

PurkkaKoodari commented Jul 26, 2022

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

  1. Open the demo in Firefox (seems to be less of an issue in Chrome).
  2. 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:

Firefox profiler results

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:

https://github.com/palantir/blueprint/blob/develop/packages/core/src/components/forms/numericInput.tsx#L235-L245

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.

@adidahiya
Copy link
Contributor

Thanks for the detailed performance report. I'm definitely open to PRs to improve component perf here.

PetrusAsikainen added a commit to PetrusAsikainen/blueprint that referenced this issue Jan 16, 2025
Number.prototype.toLocaleString is relatively slow on Firefox, and is
currently heavily used by NumericInput.getDerivedStateFromProps (which
further calls isFloatingPointNumericCharacter on each character of the
current value).

This improves the situation in two ways:

- Caches the regexes generated by isFloatingPointNumericCharacter
- Only calls roundAndClampValue when necessary in getDerivedStateFromProps
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants