primefaces / primeng

The Most Complete Angular UI Component Library
https://primeng.org
Other
10.34k stars 4.57k forks source link

Table, pFrozenColumn: Frozen columns are extremely slow and kick off many change detection cycles #14579

Closed natebundy closed 7 months ago

natebundy commented 9 months ago

Describe the bug

The pFrozenColumn directive is kicking off an extra change detection cycle for every table cell that contains the directive. For example, with a table with 90 rows that each have a td as part of a frozen column, 90 extra change detection cycles happen. For a table with 2 frozen columns with 90 rows, 180 extra change detection cycles happen.

(The directive also kicks off unnecessary cycles when using pFrozenColumn with a false frozen input for dynamic frozen columns since setTimeout is being called either way)

In addition to the high number of change detection cycles, the frozen column code in updateStickyPosition is blocking the main thread and causing layout thrashing, which is freezing the UI for several seconds (and for one of our power users with a huge amount of data, over a minute!) with decently sized tables. This happens when we initially draw the table, when clearing a search, or doing any operation that causes frozen columns to be redrawn. For virtual scrolling up in large tables with a frozen column with all of the data loaded (especially when showing an additional frozen column, such as checkboxes for multiple selection), this causes several seconds of the browser thrashing with a blank table before finally being able to draw the table again. Setting the styles this way is potentially causing the browser to reperform layout for every single cell in a frozen column every time that table cell is initialized.

Environment

Slowness with table began when upgrading PrimeNG from 14 to 16. Nothing special about our environment.

Reproducer

https://stackblitz.com/edit/github-ddsd3p

Angular version

17.0.8

PrimeNG version

17.3.1

Build / Runtime

Angular CLI App

Language

TypeScript

Node version (for AoT issues node --version)

18.18.2

Browser(s)

No response

Steps to reproduce the behavior

Using the provided StackBlitz:

  1. Notice change detection cycles caused by loading a table with frozen columns

  2. Clicking "redraw table" will start change detection count at 0 and reload the table data. Notice how many cycles it takes to reload the table

  3. Search for something (e.g. "James") then notice how many change detection cycles happen when clearing out the search

  4. Click toggle table type and switch to the table without frozen columns, then repeat steps 1-3 and notice how many fewer change detection cycles happen

  5. Try searching while the change detection cycles are counting up on the table with frozen columns and notice that the search cannot respond until the change detection cycles are finished

  6. Notice how choppy scrolling is while the change detection cycles are firing

Expected behavior

Ideally, frozen columns should be implemented in a way that kicks off no more than 1 extra change detection cycle per column (or even 0 or 1 total extra cycles), no extra cycles for dynamically frozen columns with a false input, and should only set styles once per column instead of once per cell. (Frozen columns will still have to be recalculated where column sizes may change - e.g. when virtual scroll brings in new items or when filtering table data - since automatic table sizing may change column sizes in such cases, but those should follow the same rules. Perhaps a ResizeObserver could handle such cases?) After upgrading from PrimeNG 14 to 16 and then 17, we've had to implement our own frozen columns in the meantime because the table performance with frozen columns has gotten so much worse.

cetincakiroglu commented 7 months ago

Hi,

Thanks for reporting the issue, could you please try and give us feedback with the v17.10.0 after this week's release?

natebundy commented 7 months ago

At first glance, while this should indeed clean up the extra change detection cycles, updateStickyPosition firing on every frozen table cell is more than likely still blocking the main thread and causing greatly delayed user interactions. I'll confirm and put up another StackBlitz that demonstrates that if it's still happening.

cetincakiroglu commented 7 months ago

@natebundy

Thanks for the feedback, I've tested with your example in my local. Running outside of the zone removed unnecessary change detection calls. Could you please test it after the release and tag me if anything is wrong?

intracloud commented 7 months ago

me too. i have p-table with 7 frozen columns and 400 rows. It's extremely slow, even Chrome shows message to close the window Thanks.

AgusEDSA commented 7 months ago

We have the same issue, a table with 12 columns, 2 frozen, on 500+ rows it starts freezing the browser.

natebundy commented 7 months ago

@intracloud @AgusEDSA when you both get a chance, try 17.10. It does seem like a marked improvement for frozen column performance for my app. Initially rendering large tables with frozen columns can still take a second or two, but once they're rendered they're much more responsive. However, we're usually maxing out at 2-3 frozen columns, so it'll be interesting to hear if this is still the case with 7.

If you immediately click and hold the down arrow on the vertical scrollbar after the table with frozen columns loads (or after pressing "Redraw table"), you can see a huge difference between these two: 17.3.2 17.10.0

17.3.2 will literally freeze to a halt on my machine while 17.10.0 keeps scrolling along.

intracloud commented 7 months ago

hi @natebundy

The performance problem isn't when scrolling up to the bottom or right left. The problem is that when the p-table loads the data, without pFrozenColumn it takes a few seconds, with pFrozenColumn 10 or 20 times longer.

This problem is the same when I have 3 or 4 pFrozenColumn columns, I have so many because there are columns that have p-buttons to execute actions on the record.

This performance problem does not exist in version 14.1.2, the data loading is fast, but the problem is that the pFrozenColumn columns do not work correctly with p-buttons or icons

Thanks.

Xapuu commented 6 months ago

After fighting the same issue with versions 16+ and 17.13, ended up with writing my own CSS instead of using the frozen mechanism. StackBlitz

It works for me, hopefully it will help someone else that ends up in this thread.

cuongbrilliantSE commented 5 months ago

@Xapuu It works when there's only one frozen column."

andromida commented 3 months ago

Are you able to have more than 2 frozen columns working? For more than 2 frozen columns, the table is messed up: check this Stackblitz

philip-42 commented 3 months ago

Is it possible that this issue was fixed in version 17.10 and re-introduced in 17.15?

shyallegro commented 1 month ago

Hi @cetincakiroglu seems this issue is back, I'm on 17.18.9

loicgasser commented 1 month ago

so 17.14 is fine and 17.14.1 is broken

loicgasser commented 1 month ago

This could be the issue: https://github.com/primefaces/primeng/pull/15302/files

AbdulKShahid commented 3 weeks ago

When setting [frozen] = true, the table slows down, with performance worsening as the number of rows increases. Please let know if there is an update on this issue. Thanks. version - 17.18.7