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

[DataGrid] Lower filter debounce delay #9712

Merged
merged 23 commits into from
Aug 14, 2023

Conversation

romgrk
Copy link
Contributor

@romgrk romgrk commented Jul 18, 2023

Closes #9657
Closes #9157

Turn SUBMIT_FILTER_STROKE_TIME into a prop and lower it to 50ms by default, and lower the QF equivalent.

@romgrk romgrk added component: data grid This is the name of the generic UI component, not the React module! feature: Filtering Related to the data grid Filtering feature labels Jul 18, 2023
@mui-bot
Copy link

mui-bot commented Jul 18, 2023

Netlify deploy preview

Netlify deploy preview: https://deploy-preview-9712--material-ui-x.netlify.app/

Updated pages

No updates.

These are the results for the performance tests:

Test case Unit Min Max Median Mean σ
Filter 100k rows ms -57.7 316.2 168.2 111.12 127.809
Sort 100k rows ms 633.3 1,119.1 633.3 918.9 165.362
Select 100k rows ms 193.2 282.5 206.3 229.58 36.141
Deselect 100k rows ms 136.6 371.1 208 224.74 78

Generated by 🚫 dangerJS against e6abe96

Copy link
Member

@cherniavskii cherniavskii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @romgrk!
Quick filter feels much better with lower debounce 👍

packages/grid/x-data-grid/src/hooks/utils/useTimeout.ts Outdated Show resolved Hide resolved
scripts/x-data-grid-premium.exports.json Outdated Show resolved Hide resolved
docs/pages/x/api/data-grid/data-grid-premium.json Outdated Show resolved Hide resolved
@romgrk romgrk mentioned this pull request Jul 18, 2023
45 tasks
@romgrk romgrk requested a review from cherniavskii July 19, 2023 20:07
React.useEffect(() => {
const itemValue = item.value ?? '';
setFilterValueState(String(itemValue));
}, [item.value]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this effect was covering the use case with a controlled filter model, where the filter model could change while the user has the filter panel open.
Without this effect, the filter input will be out of sync with the actual filter model:

With effect: https://codesandbox.io/s/gracious-khayyam-2xqw3n?file=/demo.tsx
Without effect: https://codesandbox.io/s/dreamy-glitter-h8h4yj?file=/demo.tsx

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've adapted the effect to respond to the model changes specifically, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll apply to the other equivalent components if it LGTY.

Copy link
Member

@MBilalShafi MBilalShafi Aug 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The effect was also making sure the value is correctly synced with header filter (which is another rendered instance of GridFilterInputValue), removing it also impacted it too, as it's actually fromInput but it still needs to be synced 😄

Before:
before-hf

After:
after-hf

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooh good catch, there's so many parts to this thing ^^

I've pushed a fix for that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, works as expected now!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@romgrk It had another aspect which I missed catching 😄
Since the rendering of GridFilterInputValue is being done from GridHeaderFilterCell, the item change is incorrectly reflected.
I am thinking of disabling this optimization (fromInput) for the headerFilters, let me know if you have better ideas.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Jul 27, 2023
@github-actions
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Aug 1, 2023
Copy link
Member

@MBilalShafi MBilalShafi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the filter response for both the quick filter and normal filter is almost instant now.
Feels much faster 🚀

@romgrk romgrk merged commit a1f6d7e into mui:master Aug 14, 2023
4 checks passed
@romgrk romgrk deleted the feat-quick-filter-delay branch August 14, 2023 15:49
@oliviertassinari
Copy link
Member

oliviertassinari commented Aug 14, 2023

Nice, this feels more responsive.

Can we create a new issue for the rest of #9657? The input lags behind now, similar to #9657 (comment). I imagine it why we can't use 50ms, and we have to stick to 150ms for now, and why we are using a debounce rather than a throttle. Or we could reopen it, as this PR gets us one step closer to do better than AG Grid.

Comment on lines +17 to +20
if (this.currentId !== 0) {
clearTimeout(this.currentId);
this.currentId = 0;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be equality fast but less JavaScript code with?

Suggested change
if (this.currentId !== 0) {
clearTimeout(this.currentId);
this.currentId = 0;
}
clearTimeout(this.currentId);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a small cost but in some places it matters.
Details here: mui/material-ui#37512

I have a few of these utils that should be migrated to core at some point.

Copy link
Member

@oliviertassinari oliviertassinari Aug 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a small cost but in some places it matters. Details here: mui/material-ui#37512

quasarframework/quasar#15203 seem to have faced something similar. Fair enough.

I have a few of these utils that should be migrated to core at some point.

  • useLazyRef: it could be great to comment on it to link Lazy useRef instance variables facebook/react#14490 I guess it's why it's here. Preferred when doing something a bit heavy to initialize the ref. Done in b9018a4
  • useTimeout: yeah, I see how this could be used in quite more places in Core.

Comment on lines +17 to +20
if (this.currentId !== 0) {
clearTimeout(this.currentId);
this.currentId = 0;
}
Copy link
Member

@oliviertassinari oliviertassinari Aug 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a small cost but in some places it matters. Details here: mui/material-ui#37512

quasarframework/quasar#15203 seem to have faced something similar. Fair enough.

I have a few of these utils that should be migrated to core at some point.

  • useLazyRef: it could be great to comment on it to link Lazy useRef instance variables facebook/react#14490 I guess it's why it's here. Preferred when doing something a bit heavy to initialize the ref. Done in b9018a4
  • useTimeout: yeah, I see how this could be used in quite more places in Core.

export function useTimeout() {
const timeout = useLazyRef(Timeout.create).current;

useOnMount(timeout.disposeEffect);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

Suggested change
useOnMount(timeout.disposeEffect);
React.useEffect(timeout.disposeEffect, []);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useOnMount has a clear semantic. It also doesn't re-allocate the [] object on every render, so less work for the GC. Very small cost again, but these add up and end up creating more frequent and longer GC pauses if we allocate objects for no reason.

Copy link
Member

@oliviertassinari oliviertassinari Aug 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit worried that it's not a problem worth an abstraction (1. It could be hard for team members to learn to use it. 2. When reviewing the code, it's someone new reviewers need to learn 3. I wouldn't be surprised if it will be missed, and even once known, the old habits will persist).

But I won't push against it, why not give it a try 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had that discussion when I added useOnMount in some older PR, but since I've seen other members of the team adopt it, so I think it's beneficial. React hooks are a bit raw, having a small set of primitives added on top of them isn't a bad idea, imho.

@oliviertassinari oliviertassinari added design This is about UI or UX design, please involve a designer and removed design: ux labels Aug 18, 2023
oliviertassinari added a commit that referenced this pull request Aug 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: data grid This is the name of the generic UI component, not the React module! design This is about UI or UX design, please involve a designer feature: Filtering Related to the data grid Filtering feature performance
Projects
None yet
5 participants