Skip to content

Pull request Improve `ComposedSectionProvider` performance on opennetltd/Composed


My overall goal here was to measure and then improve all common API usage. This boils down to:

  • Appending new sections and section providers
  • Inserting new sections and section providers at arbitrary positions
  • Reading the section offset for a given section or section provider

The test results are as follows, comparing to ea6375881e2636b253ab1138ab23bbe99cdf4c1a (which we use now). As you can see, everything is faster, with testPerformanceOfAddingManyChildrenWithManyNodesInTree being much faster now.

| Test | ea6375881e2636b253ab1138ab23bbe99cdf4c1a | Now | |------|-------|-----| | testPerformanceOfFindingLastSectionOffset | 0.0000322 s | 0.00000792 s | | testPerformanceOfFindingLastSectionProviderOffset | 0.00105 s | 0.000683 s | | testPerformanceOfFindingSectionProviderBeforeLastOffset | 0.0000326 s | 0.0000118 s | | testPerformanceOfFindingSectionBeforeLastOffset | 0.00107 s | 0.000712 s | | testPerformanceOfAddingManyChildrenWithManyNodesInTree | 21.3 s | 0.0668 s | | testPerformanceOfAddingManyChildrenToSingleComposedSectionProvider | 0.000196 s | 0.000115 s |

Note that this is testing some specific hot paths (namely appending) and the non-hot-paths.

Also note that these are extreme tests; we end up with over 19,500 total sections. The most I've seen in the app is more like 700-800.

There are a few different things contributing to this speed up:

  • [x] Removal of AggregateSectionProvider.
    • This is mostly an issue when the client app is freshly launched and has a lot of conformances. It's always nice to avoid a conformance check though.
  • [x] The ComposedSectionProvider now sends itself as the provider for delegate calls
    • This means that all the section offset mapping is done for direct descendants, which we can create an optimised path for.
  • [x] ComposedSectionProvider.providers is no longer computed, so lookups are much faster.
  • [ ] Fully remove SectionProviderMapping.
    • This was trying to cache various lookups but really it was just contributing to some of the slow downs because it was trying to create a top-level cache of offsets. We can rely on ComposedSectionProvider directly now for this.
  • [ ] Apply the same optimisations to FlatSection
    • I would say this is out of scope for this PR.

Pull request Xcode 16 update - crash fixes and enable strict concurrency on opennetltd/Composed


This PR has a few changes rolled in to one. This is being used with the Xcode 16.1 changes in the main app.

  • Strict concurrency has been enabled, which required adding @MainActor is a few places. This is going to supersede https://github.com/opennetltd/Composed/pull/4.
  • CellUpdateMethod has been added, which allows us to perform a reconfigure rather than a reload, improving the performance when the layout has not changed.
    • This was originally added as a workaround for a crash in the iOS 18 SDK. It's still used by OneTimeCodeInputSection.
  • A crash relating to the iOS 18 SDK has been fixed.
  • Support for table views, stack views, and Core Data sections has been removed to reduce the amount of maintenance we have for this package.

Pull request Remove elements provider cache on opennetltd/Composed


This is a relatively small change to remove the elements provider cache from CollectionCoordinator.

This will have some performance impact, but I am opening this as a draft because if we find a method of recreating the header bug I would like to test this change.

To actually incorporate this change we should update all the SingleUICollectionViewSection.section(with:) implementations to cache what is returned, otherwise the impact may be too large. Since most sections don't actually care about the trait collection we could update SingleUICollectionViewSection to require a property (which we then implement using a lazy private(set) var) rather than a function and add a separate protocol for varying by trait collection.

We stand to benefit from caching the values returned by SingleUICollectionViewSection implementations even without these changes, but for now I am focussed on recreating the header bug.

Pull request Compositonal layout improvements on opennetltd/Composed


This PR is primarily focussed on improving support for compositional layouts, however it also provides some improvements for flow layouts too.

  • Swift version has been updated to 5.9 (our current minimum)
  • iOS version has been updated to 14 (our current minimum)
  • An assertion has been added to UICollectionViewCompositionalLayout to ease debugging section providers that include children that have not yet adopted CompositionalLayoutHandler
  • debugLog has been updated to use an auto closure for the message
    • This is unrelated to other changes but provides a small performance improvement when debug logs are disabled
  • Supplementary view updates have been moved to a separate batch updates
    • Without this some updates will crash on iOS 17 with a compositional layout (see https://github.com/opennetltd/ComposedUITests/commit/4f54a1f19c81e6fa2f5354bd714f045e1c39a8be)
    • This has the bonus of always using the correct index path during a batch updates, which should be an improvement for flow layouts too

xcutils v0.4.0


Release Notes

  • Improve release process
  • Increase Swift version 5.9
  • Increase macOS version to 13