Skip to content

FXIOS-15033 - [Performance] - Cache normal/private tabs to avoid redundant O(n) filters on every access#32378

Open
PARAIPAN9 wants to merge 5 commits intomainfrom
paraipan/tabs-performance-improvements-using-cache
Open

FXIOS-15033 - [Performance] - Cache normal/private tabs to avoid redundant O(n) filters on every access#32378
PARAIPAN9 wants to merge 5 commits intomainfrom
paraipan/tabs-performance-improvements-using-cache

Conversation

@PARAIPAN9
Copy link
Collaborator

@PARAIPAN9 PARAIPAN9 commented Mar 4, 2026

📜 Tickets

Jira ticket
Github issue

💡 Description

  • normalTabs and privateTabs are accessed frequently across many classes.
  • Previously every call to normalTabs or privateTabs triggered a separate O(n) filter. Now both are computed in a single O(n) pass and cached until tabs changes.
  • Wrote unit tests.

📝 Checklist

  • I filled in the ticket numbers and a description of my work
  • I updated the PR name to follow our PR naming guidelines
  • I ensured unit tests pass and wrote tests for new code
  • If working on UI, I checked and implemented accessibility (Dynamic Text and VoiceOver)
  • If adding telemetry, I read the data stewardship requirements and will request a data review
  • If adding or modifying strings, I read the guidelines and will request a string review from l10n
  • If needed, I updated documentation and added comments to complex code

@PARAIPAN9 PARAIPAN9 requested review from Cramsden and lmarceau March 4, 2026 11:56
@PARAIPAN9 PARAIPAN9 requested a review from a team as a code owner March 4, 2026 11:56
@mobiletest-ci-bot
Copy link

mobiletest-ci-bot commented Mar 4, 2026

Warnings
⚠️ Detected tab related changes in: firefox-ios/Client/TabManagement/TabManagerImplementation.swift (cc @lmarceau)
Messages
📖 Project coverage: 40.28%

💪 Quality guardian

1 tests files modified. You're a champion of test coverage! 🚀

🧹 Tidy commit

Just 2 file(s) touched. Thanks for keeping it clean and review-friendly!

✅ New file code coverage

No new file detected so code coverage gate wasn't ran.

Client.app: Coverage: 38.39

File Coverage
TabManagerImplementation.swift 56.2%

Generated by 🚫 Danger Swift against ca4b747

if let cached = _tabSplitCache { return cached }
var normalTabs = [Tab]()
var privateTabs = [Tab]()
normalTabs.reserveCapacity(tabs.count)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we want to reserveCapacity for normal tabs, but not private tabs. Also, the amount of tabs.count isn't directly the capacity we should allocate for normal tabs since it includes private tabs. So I'm just trying to understand the performance gain here, and if this really makes a difference considering this bit of documentation

The Array type’s append(_:) and append(contentsOf:) methods take care of this detail for you, but reserveCapacity(_:) allocates only as much space as you tell it to (padded to a round value), and no more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I used reserveCapacity only for normalTabs because normal tabs are usually more numerous than private tabs, and to avoid CoW array reallocation. Even though append is amortized O(1), if the array grows significantly it needs to reallocate multiple times, creating overhead. For example, with 100 normal tabs, appending without a reserved capacity would trigger around 8 reallocations, each an O(n) operation. By using reserveCapacity upfront, space is already allocated and every append is guaranteed O(1). Here's an interesting documentation section: https://developer.apple.com/documentation/swift/array#Growing-the-Size-of-an-Array.

@lmarceau
Copy link
Contributor

lmarceau commented Mar 4, 2026

First round of review ^^ I still want to make some tests with those changes

@lmarceau lmarceau self-requested a review March 4, 2026 16:07
@Cramsden
Copy link
Contributor

Cramsden commented Mar 5, 2026

Can we do some profiling/bench-marking on the improvement here? I would love to know what kind of speed ups we see with 100 tabs before adding additional complexity to the tab code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants