SoySauceLab / CollectionKit

Reimagining UICollectionView
MIT License
4.4k stars 259 forks source link

No Prefetch? Scroll performance issues #86

Closed agotfredsen closed 6 years ago

agotfredsen commented 6 years ago

Hi . First great work with CollectionKit . I Love it but I have huge performance issues with it. And noticed some strange things.

There are no prefetch and no preload of views(cells) . running simple print() debug I can see that the views are created just as they become visible . That can't be right . That creates huge performance issues when scrolling . I need to be able to draw the view graphics before it enters the visibleframe.

Looking at for example Texture by Facebook https://github.com/texturegroup/texture .. they preload not only one but 2-3 cells/views/nodes before becoming visible in order to get 60 fps scroll

There are no control of how many view I would like to preload / prefetch

I really really like this kit but I can't use it because of this ... and I really would not like to rewrite all of my code ...

lkzhao commented 6 years ago

There is a method to control whether or not to preload the cell. It is currently controlled at the layout level.

You can use insetVisibleFrame(by insets: UIEdgeInsets) and specify a negative insets to achieve the preloading effect.

However this doesn’t necessarily improve scrolling performance. It does let you prefech data for those cells. But it still takes main thread time to decode and rasterize text. it is just that this will not happen when the cell become on screen, but at a different time. The way that texture improves performance is mostly due to background layout, rasterization and decoding.

In the end, CollectionKit’s goal is not to have better performance than UICollectionView.

lkzhao commented 6 years ago

There is the possibility of combining Texture with CollectionKit.

However, nowadays, devices are very capable of doing 60fps as long as you don’t decode images on main thread. I usually use PINRemoteImage with CollectionKit, and I have no performance problem.

As device becoming faster, there even less reason to optimize this part of the application.

agotfredsen commented 6 years ago

You can use insetVisibleFrame(by insets: UIEdgeInsets) and specify a negative insets to achieve the preloading effect.

That did the trick . Now it works great :) Thanks

Banck commented 6 years ago

Hello! I have the same issue, but my cells are creating from nib, and when user scrolls, every cells are creating from nib and fps is drpopping.

    func fromNib<T : UIView>() -> T? {
        guard let contentView = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? T else {
            return nil
        }
        addSubview(contentView)
        contentView.fillSuperview()
        return contentView
    }

I've tried to create pull of cells and reuse them, but then I have another issue. When some cell was removed there is some blank spaces between cells (http://joxi.ru/n2YY4bHoLQQg26). I uses AnimatedReload animator from example, the same issue with WobbleAnimator. What I've tried:

        var cells: [MatchCell] = []
        for _ in 0..<50 {
            cells.append(MatchCell())
        }

        let sourceView = ClosureViewSource(viewGenerator: { (data, index) -> MatchCell in
            if cells.count - 1 < index {
                let cell = MatchCell()
                cells.append(cell)
            }
            return cells[index]
        }, viewUpdater: cellUpdater)

I've tried to do

 cell.frame = .zero
            cell.transform = .identity
            cell.alpha = 1.0

in cell updater, but the same issue. Some screenshots: http://joxi.ru/Q2KjMlI4Vo6Lmj http://joxi.ru/52aJdbu4VaQkA0

@lkzhao could you help me somehow? Thanks!