[regression] The tab tray can hang for 2-3 seconds when closing tabs or switching between tabs
Steps to reproduce
- Open 10+ tabs with different web pages.
- Open the tab tray and tap to switch to different tabs.
- Then swipe to close tabs.
The performance problem seems to get worse as I open more tabs, even if I close most of the tabs.
Expected behavior
Closing tabs and switching to a tab should be fast.
Actual behavior
Closing tabs or switching between tabs in the tab tray can hang for 2-3 seconds before shifting tabs in the tab tray or opening the tab.
Device & build information
- Device: iPhone 15 Plus running iOS 26.0.1
- Build version: Firefox 9000 (63602)
- First seen version: Maybe 144.3?
I tested some older TestFlight Beta builds and I think the slow tab tray is a regression in version 144.3.
I’m not confident because the problem is intermittent, but I definitely experience the slow tab tray in 144.3 and recent 9000 builds. I don’t think I see the problem in 144.2, 144.0, or 143.2.
┆Issue is synchronized with this Jira Task
Related trashcan-closing many tabs:
- https://github.com/mozilla-mobile/firefox-ios/issues/30492
While investigating #30195 I ended up with very long hangs when trying to close or open PBM tabs at that point, even with 2-3 tabs in normal mode and none/first in PBM.
https://github.com/user-attachments/assets/a94b9719-fef4-4386-93ce-3a5bfef5ec35
At which point it seems to hang for seconds even coming back to a tab from menu or tab tray:
https://github.com/user-attachments/assets/6ccc0222-658f-4cbd-86ed-fc8243ef09ca
I'm having the same issue for the last 1-2 weeks. It sometimes takes up to 4 seconds to open or close a tab in firefox. Very annoying, makes the browser close to unusable. Device: iPhone 15 OS: iOS 17.6.1 Firefox version: 145.0 (63787)
I'm going to start looking into a solution for this. If I find something I'll open a PR.
I managed to capture this hang inside of the XCode profiler. I'm pretty sure it's being caused by high CPU usage on the main thread. The issue seems to relate to Store.executeAction, which is responsible for synchronizing the browser state with the other components of the browser. The point of confusion right now is "Why would the execution time of this function grow in relation to how many tabs have been opened on the device?"
I'll need to keep digging with the debugger in order to answer this. Maybe a collection is growing unexpectedly? I suspect the solution will be one of two things. Either moving work into a non-main thread, or finding some way to reduce the size of a collection that's being iterated here.
my two cents as a user, this is what I have noticed for this specific issue:
- I noticed the issue after updating my device to the newer iOS 26 (this might be a red herring)
- if I fully close firefox, and open it fresh (with X tabs), it seems to perform ~ok for the first ~10 minutes
- the more time pass on / or maybe the more navigation + tab switching happens: the more noticeable this hang becomes (my worst has been ~5 seconds to expand the tab after tap on it with my finger)
- I had the issue with 20-30 tabs but also with less, like 10-15 tabs also happens, and as mentioned closing and reopen kind of helps but it gets bad relatively quickly
My main sites are youtube (prefer the browser than the app), e-commerce sites
So I think @Xaeroxe is on the right track with Maybe a collection is growing unexpectedly, definitely something is growing/worsening with plain usage or with time.
specs:
- Device: iPhone 13 Pro
- OS: iOS 26.1
- Firefox version: 145.0 (63787)
One symbol keeps coming up over and over again with really long execution times:
__40-[UIView(Hierarchy) layoutBelowIfNeeded]_block_invoke
So this could be related to the warnings I'm constantly getting that look about like this
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSAutoresizingMaskLayoutConstraint:0x137b4e9e0 h=-&- v=-&- _TtC5UIKitP33_DDE14AA6B49FCAFC5A54255A118E1D8713ButtonWrapper:0x137aeec00.minX == 0 (active, names: '|':_TtGC5UIKit22UICorePlatformViewHostGVS_32PlatformViewRepresentableAdaptorVS_P10$19840420020ButtonRepresentation__:0x1361e6f80 )>",
"<NSAutoresizingMaskLayoutConstraint:0x137b4ea30 h=-&- v=-&- H:[_TtC5UIKitP33_DDE14AA6B49FCAFC5A54255A118E1D8713ButtonWrapper:0x137aeec00]-(0)-| (active, names: '|':_TtGC5UIKit22UICorePlatformViewHostGVS_32PlatformViewRepresentableAdaptorVS_P10$19840420020ButtonRepresentation__:0x1361e6f80 )>",
"<NSLayoutConstraint:0x137b4c870 _TtC5UIKitP33_DDE14AA6B49FCAFC5A54255A118E1D8713ButtonWrapper:0x137aeec00.width == _UIButtonBarButton:0x1361e6d00.width (active)>",
"<NSLayoutConstraint:0x137b4f430 '_UITemporaryLayoutWidth' _TtGC5UIKit22UICorePlatformViewHostGVS_32PlatformViewRepresentableAdaptorVS_P10$19840420020ButtonRepresentation__:0x1361e6f80.width == 0 (active)>",
"<NSLayoutConstraint:0x137b4ca00 'IB_Leading_Leading' H:|-(2)-[_UIModernBarButton:0x135525180] (active, names: '|':_UIButtonBarButton:0x1361e6d00 )>",
"<NSLayoutConstraint:0x137b4ca50 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x135525180]-(2)-| (active, names: '|':_UIButtonBarButton:0x1361e6d00 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x137b4ca50 'IB_Trailing_Trailing' H:[_UIModernBarButton:0x135525180]-(2)-| (active, names: '|':_UIButtonBarButton:0x1361e6d00 )>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
I have a .trace file that I'm ready to email to anyone who wants it. I'd just post it here but GitHub is refusing to let me upload it.
@Xaeroxe You should be able to zip that trace, and upload a .zip here (the GH UI should tell you something like that when it doesn't allow you to upload a file type it doesn't like.)
Really sorry about the Google Drive link, but no matter how I try I just can't get this file under the limit that GitHub imposes. So here's the Google Drive link. The problem starts happening after the 6:30 mark in this file.
https://drive.google.com/file/d/11oFf705msiRLN1e73utFJ8_DNg4ff111/view?usp=share_link
I've been noticing poor performance when opening and closing tabs as well. 10+ tabs, happens only when switching, opening or closing tabs through the tab menu. Swiping the address bar left or right to switch tabs is responsive as expected.
Device: iPhone 13 Pro Max iOS version: 26.1 (23B85) App version: 145.1 (64317)
I have a user report of severe slowness of opening tabs. I verified myself that there is at least a 3 second delay between tapping on a tab and that tab popping out and opening. There are only about ten tabs in private browsing mode where this was tested.
iPhone 17 Pro, iOS 26.1 Firefox 145.2 (64514)
The user noted that they have observed this issue of slowness for a longer while, possibly 2 to 3 weeks.
Is there anything that I can do to capture useful information? I am a Firefox engineer who have worked on desktop and Android before, and also used Instruments in Xcode to investigate performance issues on desktop. I have however never debugged on iOS before.
@Rob--W well I captured my own performance data relating to this and posted it. The trouble at this point is that the fix seems to be non-trivial. I believe it will involve making alterations to the UI layout constraints. Really the thing this issue needs right now is attention from someone more familiar with those constraints. I began by treating it as an optimization problem, but since it's actually an issue with the UI layout I dropped it. It quickly got more involved than I felt comfortable doing for my first PR.
@Xaeroxe How did you capture the performance data? I'd like to do the same to confirm whether it's the same issue.
I followed the directions here https://developer.apple.com/tutorials/instruments/identifying-a-hang