StickyTableHeaders icon indicating copy to clipboard operation
StickyTableHeaders copied to clipboard

Scrolling freezes when at the top of long table

Open YoDevv opened this issue 10 years ago • 5 comments

I have a large table with 3000-4000 rows. Scrolling up/down anywhere except at the top of the table is normal, without lag. But when at the top of the table (either when the page first loads, or when returning to the top), the page/scrolling freezes a few seconds while presumable StickyTableHeaders makes calculations. See this example: https://jsfiddle.net/x25Lxynq/6/ . I have tried this in Firefox 36.0.4 & IE 11.

Is there any way/change to speed things up and avoid the lag ?

YoDevv avatar Mar 24 '15 16:03 YoDevv

large table with multi rows and columns ,header freeze and hold for few second when scroll to no floating header

eagoo avatar Jun 29 '15 09:06 eagoo

anyone fix it?

eagoo avatar Jul 14 '15 04:07 eagoo

Maybe this is related to #61. It seems I have found some issue and implemented some workaround that fixes 90 % of the issue in my case.

Observations and assumptions:

  • Firefox seems to render the page more synchronously than Chrome. In both browser, there is some relatively heavy computation (you can see hundreds of milliseconds in profiler), but Chrome does not wait for the JS. Firefox results in significantly laggy scrolling, while Chrome results in sticky header being shown after some delay. Of course, the issue is much more visible in Firefox, but this does not mean that the issue is non-existent in Chrome.
  • When I scroll, the toggleHeaders function is called. Some more handlers might be called in some cases (see bind function), but not in my case.
  • When scrolling above the table (i.e. the table header is below the top of the visible part of document) and having fixedOffset: 0 and scrollableArea: window, there are few candidates for heavy computations in the handles (other computations are trivial or unreachable in this case):
    • $this.offset()
    • base.$scrollableArea.scrollTop()
    • base.$scrollableArea.scrollLeft()
    • $this.height()
    • base.$clonedHeader.height()
  • All of these computations are also performed when scrolling within the table. But when scrolling within the table, the scrolling is smooth. So, some of these computations seems to be more complex when scrolling above the table than when scrolling within the table. My candidate for that is base.$clonedHeader.height(), because it is hidden when scrolling above the table, so the computation is probably not so trivial. (Maybe the element is not rendered, so the .height() call causes rendering every time it is called.)
  • The notScrolledPastBottom is sometimes evaluated needlessly. That is, when scrolledPastTop is false, then there is no need to evaluate notScrolledPastBottom, but it is evaluated anyway.

Possible solutions:

a. Do not evaluate notScrolledPastBottom if not needed. This approach is very simple to implement, as notScrolledPastBottom value is used only once. Implementing this removed the lags when scrolling above the table. However, when visibility of sticky header is to be changed, it is still laggy. Moreover, it is likely to be laggy when scrolled below the table (i.e. nothing from the table is visible and the table is above the visible part of the document). b. Compute the height from $originalHeader rather from $clonedHeader. This should make the computation on a visible element and solve the issue. I am, however, unsure if there is some reason why $clonedHeader is used over $originalHeader. It seems to be OK in my case, but there might be some edge case. Maybe the author of the library can comment that.

Note that the issue will probably appear again when the table is hidden or in some similar edge case. But I am not sure if it is worth bothering with it.

Results

I haven't done deep testing, but any of there two approaches seems to do a good job, at least on my page with Iceweasel (i.e. Firefox branded by Debian) version 41.0. They also seem to do a good job when combined together. There is still some lag when the visibility of sticky header is toggled, but it is much better than it used to be. You can compare my current version of the page to some previous one. The previous one uses StickyTableHeaders 0.1.17. The current one uses my patched version (with both patches).

v6ak avatar Oct 04 '15 18:10 v6ak

I'd like to remove the last lag – when the cloned table header is shown or hidden.

a. Use native CSS DOM instead of jQuery – this does not seem to help much. b. Never use display: none for the cloned column. I've tried several solutions, none of them worked:

  • position:fixed; top: -999px caused miscalculation of column sizes, as it is computed when detached
  • height: 0px; overflow: hidden seems to be simply ignored in thead (at least in Firefox)

c. Calculate the header widths in updateWidth on the original header — causes some miscalculations, I don't know why. Moreover, it does not even seem to remove the lag, so there might be also another problem. d. Use base.$originalHeader.width() instead of base.$clonedHeader.width() in updateWidth — does not help much.

v6ak avatar Oct 05 '15 17:10 v6ak

For Gecko and Trident, it seems that queuing some updates adds smoothness. For Blink, it seems that synchronous (current) approach is better, because the renderer is more async and doing it even more async makes it feeling lazy with no benefit.

I know, UA sniffing is bad, but I don't know a better way there. Feature detection cannot be used there, we would need rather something like performance detection, which is not what I would want to implement (for hopefully obvious reason). Moreover, the risk of bad UA sniffing is just choosing the non-optimal way, not an incompatibility.

There is the patch: https://github.com/v6ak/zbdb-stats/commit/542ae80913336f5e2625ff271fca0715f6e0d3be

v6ak avatar Oct 04 '16 11:10 v6ak