I've been shilling for Firefox for years. It is my primary browser for both development and personal use. But I still think it has some catching up to do with Chrome.
I have a web app that allows customers to make templates for their standard operating procedures that they pull from our main product. For writing steps and substeps, I use a WYSIWYG HTML editor called TynyMCE. I went with it because I was able to implement it in an afternoon, their licensing was compatible with our use, and I had a tight deadline.
We failed to anticipate just how large some of the templates clients would be making, so sometimes when they open a template they end up having a couple hundred of these editors hidden behind drag and drop enabled accordions.
Firefox chokes on the initial TinyMCE calls for these large templates, taking quite a long time to fully render the page. Once it's done, everything is nice and snappy, but it's like a 20-30 second wait after the wire even on my beefy 5900x.
Chrome seems to handle this just fine.
It's possible that the culprit is a bad polyfill or a Firefox-specific bug in TinyMCE, I haven't put much work into diagnosing it yet beyond verifying that TinyMCE is eating up all the CPU time. For now my planned solution is to just write my own WYSIWYG editor, because TinyMCE ultimately offers a lot more than we actually need, and it was only a stopgap solution to get out a polished MVP. But needless to say, for the first time in years, I found myself spending a non-trivial amount of development time in Chrome. Sadly I've never actually had a client use this app with anything other than Chrome or Safari, so this is naturally a low-priority issue.
If you could grab a profile of the problem with the Firefox profiler and file a bug it would be greatly appreciated. From the sounds of it it's probably an edge-case we're not aware of where Firefox performs very poorly. The problem with this kind of things in Mozilla is that we're often blind until someone brings up the issue and notifies us.
Is there a public demo or test page for TinyMCE that reproduces the hangs? If not, you could use Firefox's built-in performance profiler to record a profile and file a Firefox bug.
I‘m on the other side of that. I'm constantly throwing large amounts of HTML at Firefox and it just goes on normally, literally 0 slowdown. Add some VueJS for additional fun. I deploy and get Chrome users complaining about performance. One example is that one can not add more than a few hundred options in an Options Select list in Chrome. You can throw literally 10'000 at Firefox. Similar stuff with text fields having 10'000s of rows.
For your own mental health, don’t. I was looking for an old article describing how bad the API is, written by one of the authors of a WYSIWYG JS editor, but I can’t find it.
Advanced Custom Fields on WordPress allows for "click to initialize TinyMCE" on areas such as that which may be a usable workaround for now. Then you only have 1 initializing at a time,
Also keep in mind although Firefox containers is made by Mozilla it's a plugin that you have install, which was very counter intuitive when I first wanted to use it.
I leave Safari as my default browser, although I actually use it the least. But I like having the same "default" experience on my desktop and phone. If I am opening a link from Mail.app or punching something into Alfred it will open in Safari. I use some light ad-blocking.
I use Chrome for work. I use Google Translate a bit and this works extra well in Chrome. Plus, Google apps and whatnot. Limited ad-blocking because I'm often using ads platforms.
I use Firefox for all my intentional/casual browsing. Maximum ad blocking.
You can also set a browser chooser as the default, and have choose which browser you want to open each link in. I’ve written my own, and it even lets me pick which chrome profile I want to open in.
Personal experience: Battery drain was always my problem with Firefox on MacOs. Why when using Safari it is nice and full day surfing w/o recharge; but doing the same with Firefox would discharge laptops battery much faster.
Did they work? Yes! Performance on lightly loaded systems was about the same as OSSpinLock but on loaded ones, they provided massively better responsiveness. They also did something extremely useful for laptop users: they cut down power consumption as a lot less cycles were wasted having the CPUs spinning on locks that couldn’t be acquired.
To no one's surprise, one has to use Apple's undocumented APIs to be able to match Safari's power use.
Battery life seems like an afterthought for anything other than Safari (and back when it was Trident-based, MS Edge on Windows), which is kinda weird when one considers how laptops have come to dominate computing.
This. Firefox drains battery, but still less than Docker & a TypeScript dev environment. Using those three together means my M1 Air falls a LONG WAY SHORT of the 18hr battery life I was promised
I’ve been on brave for about 2 years now and all I see people talk about is Firefox. Should I swap? I thought people liked brave but I really don’t see it mentioned anymore.
Depends what you care about. I think there are two main reasons to use Firefox over Chrome:
- better privacy protections
- not wanting to leave web standards entirely to Google/Apple (for-profit corps)
Brave attempts to address the first, but does little about the second as it uses Blink (i.e. Chrome's engine). Personally, I care a lot more about the second.
I use Brave and Firefox primarily on my Linux computers (and Safari on MacBook for battery reasons already mentioned). I just switch between them for different purposes. Usually Brave for Gmail or Google Docs, and Firefox if I need some extension not available in Brave (Firefox still seems to have more robust extension capability).
Same situation. I switched to Brave a couple of years ago (from Firefox) and I occasionally check in on Firefox to see if I should switch back. I haven't seen a reason yet. Things like full screen support in YouTube sees a bit janky still. I like where Brave is going with getting rid of cookie consent and other annoyances without extensions.
Do you care about vertical tabs? (if not, you must not have many tabs open at once) If so, your choices are: Opera, Edge or Firefox with one of two extensions (I use Sidebery).
I wonder whether this could be related to "profile bloat" or something.
It's not a direct apples to apples comparison, but my anecdotal evidence, on Linux, is the opposite. I usually use Firefox on my Linux/X11 box, but every now and again I fire up Chromium and always get the feeling that it's much snappier.
I may be mistaken, but I have found the Microsoft Edge to have done considerable catching up. In my Mac and on PC, it beats Chrome anyday in performance and ease of use. I understand that Microsoft have reasons to invest heavily on a modern, nimble browser. But do we have any other reasons - like trying to conquer a new market etc. Behind this?
* CPU Usage is extremely higher than in chrome for video call/meeting related websites.
* Font rendering is horrible on a lot of websites. I think this is more fault of the website developers, but it doesn't change the fact that I as end user with Firefox have subpar experience.
* The native OS integration seems very janky, from swipe to go back, to pinch to zoom, something feels off about them.
* I've encountered a lot more websites that didn't quite work smoothly. This is same as one of the points above of web developers being at fault here, but it still doesn't change my experience with FF.
I want to use Firefox, but not if it degrades my experience - which it currently very noticeably does.
This blog post has some good discussion about what makes a good locking primitive. On macOS, os_unfair_lock is generally a good choice for many applications. That said,
> At this point, you might wonder if os_unfair_lock – possibly coupled with the undocumented flags – would be a good fit for your codebase. My answer is likely yes but you’ll have to be careful when using it.
I would hesitate to give this advice. The overwhelming majority of applications on macOS do not have performance profiles like Firefox does. The system allocator (rather than jemalloc) is the right choice for all but very few use cases. There are a vanishingly small number of usecases where using the undocumented flags is appropriate.
The rules are different when you’re a popular browser with an existing relationship with Apple and dozens of smart engineers who can (at least in theory) understand the consequences of using this API, and leverage an existing relationship with Apple to ensure that it doesn’t become a liability in the future as the platform evolves. For pretty much everyone else, this should be nothing more than a “wow, neat” blog post.
> leverage an existing relationship with Apple to ensure that it doesn’t become a liability in the future as the platform evolves
I sincerely doubt that Firefox can leverage anything with Apple, or that Firefox engineers have much of a relationship at all with Apple. Who does, really.
I'm not sure it matters though. Many smaller Mac developers have a long history of using private API, and it's largely fine. There's no truly "safe path" with Apple, because Apple does whatever it wants whenever it wants, and I've seen them break "supported" API plenty of times, and leave it in a broken state. But the risks of any given brokenness are small, and you can't predict what will break from year to year, so what can you do except go with what works, and hope for the best.
It's certainly fair to say that the majority of applications on macOS do not have the performance profiles of Firefox, but it's also the case that the majority of applications weren't even using lower level primitives like OSSpinLock in the first place, so replacing it was not a concern.
With all due respect, you’re a small indie developer, and the situation is different when you make a browser used by millions of people. Apple does do whatever it wants, but sometimes it (wisely) realizes that what it wants is people to not be upset that people’s favorite app is broken in the next release of macOS, so occasionally steps are taken to ensure that doesn’t happen. This ranges from committing to SPI for longer than it is necessary for Apple’s own use, to putting in bundle ID or linked-on-or-after checks, or in rare cases reaching out to developers directly.
The target for this comment is developers like you, but those who are less familiar with the platform than you are but of similar import. Those are the ones who will read this and say “wow Firefox says this is how to make my app fast so I should do it!!1!” and what is going to happen is either they’re going to use it wrong, because they aren’t really experts on how locking works, or they’ll copy the code of of Firefox and their app will break in a future OS release while Mozilla will update their code in July.
Happily, rather than using non-API OS internals, Firefox could recognize that their behaviour does not match normal applications and so they might have to actually implement spin locks themselves rather than relying on a API that is designed to support more general apps. That's what the other browser engines do, including webkit and that's an actual system library on macOS and iOS.
The solution here, rather than using OS-internals is for Firefox to implement spin locks themselves, which is the level that they should be thinking if they're making their own allocator. This is what webkit, chromium, etc - webkit even has a blog post: https://webkit.org/blog/6161/locking-in-webkit/
> As an intermediate solution, I initially fell back to OSSpinLock on older systems. Later I managed to get rid of it for good by relying on os_unfair_lock plus manual spinning in user-space.
Have you looked at `__ulock_wake` versus `os_unfair_lock_with_options`? __ulock_wake is another private darwin API for locking.
From some Zig code:
// Darwin XNU 7195.50.7.100.1 introduced __ulock_wait2 and migrated code paths (notably pthread_cond_t) towards it:
// https://github.com/apple/darwin-xnu/commit/d4061fb0260b3ed486147341b72468f836ed6c8f#diff-08f993cc40af475663274687b7c326cc6c3031e0db3ac8de7b24624610616be6
//
// This XNU version appears to correspond to 11.0.1:
// https://kernelshaman.blogspot.com/2021/01/building-xnu-for-macos-big-sur-1101.html
//
// ulock_wait() uses 32-bit micro-second timeouts where 0 = INFINITE or no-timeout
// ulock_wait2() uses 64-bit nano-second timeouts (with the same convention)
Post author here, `__ulock_wait2` is used under the hood by `os_unfair_lock()`. I considered it but it would have required more scaffolding, especially to support all the versions of macOS we care about. We might use it in the future though.
The go-to synchronization primitive on Windows, critical sections[1], does a short spin in then waits.
To me it has always seemed as a decent strategy, and when working on a cross-platform heavily multi-threaded code base which had a fairly contested hot-spot, Windows performed quite well using just plain critical sections.
It's so clear how Mac OS and Windows both can function without app stores that it's obvious that app stores are a rent-seeking middle men. Terrible that they've been normalized for mobile devices.
I don't see any issue with the app store models for macOS (mostly) and windows (could be useful, but not in its current implementation). They act as more curated package managers with a GUI, and an added bonus of taking care of payments (a hard problem!).
App stores allow users a centralized place to both acquire known and verified applications as well as get updates for them. They are a safe place to buy things - Apple is not going to steal your credit card. For developers, they are a convenient place to park your app, without having to manage your own distribution services. And payments is always pain - it's probably the single biggest value add that the app stores cover it for you.
And you can always circumvent it on these platforms. It's just an addition. I'd prefer to get an app on the mac app store if it is there, if it is not then that is fine as well, but will require more digging to verify it's authenticity.
I think the problem is locking us to one app store - because the app store does provide some added functionality (easy of use - one place to go for all apps - security vetting - automated update settings across apps)
The App Store on macOS is a convenient distribution channel. It’s helpful to have, especially because alternatives exist if it doesn’t have the right tradeoffs for you.
While I'm all for opening devices up the fact that app stores exist on platforms like Windows or Mac disproves the rent-seeking thesis if anything. Steam commands a 70/30 cut while software can be distributed freely on Windows which was in fact the normal situation on desktops before the advent of app stores.
App stores are distribution mechanisms and advertisement channels, same value proposition as Spotify compared to shipping your music on your own website.
I think the day that Apple completely bans non-App Store apps is approaching very quickly. It became apparent when Mac OS started checking app signatures with a remote server a couple of OS releases ago and wouldn't let you open them in some cases even if you right click-opened. I wonder how many technical users will stay with Mac OS if Apple decided to go that route.
I have the VPN problem too. For me, it's a proxy thing. My company puts an HTTP proxy in-place inside of their VPN, and Firefox picks up the settings from MacOS.
When I disconnect from VPN, Firefox still has the VPN's proxy settings. I have to restart it to refresh Firefox's cached proxy settings. So that means I effectively have to restart Firefox any time I change between VPN and non-VPN.
If that's your problem too, then I don't have a fix for it. I'd love to hear if anybody else does though.
as someone with many tabs across many windows across many desktops/spaces, one weird trick i found is that when firefox starts up (on an intel MBP, 2019), it will churn CPU at over 100% until you go and foreground each of the windows in each of the workspaces. then the CPU usage becomes normal. perhaps it has to do with extensions like noscript or ublock origin, or my propensity to start firefox without internet access, but i don't think that matters here. not sure why this happens, but it's been required across at least the last few firefox restarts for me.
1 happens to me as well. And I even use the Mozilla VPN. I noticed it also happens with Cloudfare's Warp. Turning it on/off or even closing the display while they are active sometimes result in complete loss of connectivity when trying to interact with a tab again.
A lot of times, I have to close the current tab and open a new one to regain connectivity.
It is my only issue with Firefox on mac, currently.
> If you’re running Firefox on macOS you might have noticed that its responsiveness has improved significantly in version 103, especially if you’ve got a lot of tabs, or when your machine is busy running other applications at the same time.
Huh, now that you say it: I haven't been all that angry at Firefox lately.
I’m curious how it was determined that the locking was causing problems? Was it just some intuition from cases with poor performance and staring at code, or some perf-like tool (I don’t really know about the landscape of performance monitoring tools for MacOS) highlighting that a lot of time was spent in locks, or some known MacOS vs others difference?
I think I also don’t understand the discussion about spinning in kernel space. Doesn’t that require context switches which the article points out have issues? I would have guessed the answer would be to spin a bit in userspace with architecture-specific instructions like pause and then syscall if the lock couldn’t be acquired. Maybe I just don’t really know how syscalls work on a Mac.
I’m also weakly curious why jemalloc needs so much locking anyway? I haven’t thought about this at all so I’m surely missing something but my guess would be allocation from per-thread pools with occasional synchronisation, and that this synchronisation would be too infrequent to have these issues.
From the blog post it seems like the team was using OSSpinLock, which was deprecated (for good reason) and then when trying to use the replacement (os_unfair_lock) degraded performance on some tests. I don’t have details on how they determined what the issues were but considering if the results were across a single change and one had access to the source it doesn’t seem all that difficult to see why there are performance differences. The various profiling tools on macOS (Instruments, mostly) would help confirm this.
Spinning in kernel space does require a transition into the kernel. But, critically, it does not require rescheduling another thread and waiting around, which is even more expensive. The kernel has the context to know what is running and what isn’t, as well as some information on who owns the lock, so it can do a pretty good job here. Spinning in userspace is bad because the thread holding the lock may be parked by the kernel, which means that you’re just spinning for no reason. If you don’t include any special instructions you burn power, and even if you do you don’t benefit from the knowledge the kernel has of whether you should just be scheduled off while waiting anyways.
> I’m also weakly curious why jemalloc needs so much locking anyway?
I'd love to hear from someone with more firsthand knowledge, but from a quick read of the implementation details for jemalloc, it seems there is a balance that has to be struck between lock contention and memory fragmentation. Too few arenas and lock contention slows you down, too many arenas (or enabling thread-specific caches) and the cache misses from fragmentation will slow you down.
the blog post also mentioned that Firefox's jemalloc is highly customized, maybe firefox's specific profile gets value out of a more lock-heavy strategy.
With all the things they've addressed in Firefox recently and with Chrome's manifest v3 nonsense, I'm running out of reasons not to switch.
I have a web app that allows customers to make templates for their standard operating procedures that they pull from our main product. For writing steps and substeps, I use a WYSIWYG HTML editor called TynyMCE. I went with it because I was able to implement it in an afternoon, their licensing was compatible with our use, and I had a tight deadline.
We failed to anticipate just how large some of the templates clients would be making, so sometimes when they open a template they end up having a couple hundred of these editors hidden behind drag and drop enabled accordions.
Firefox chokes on the initial TinyMCE calls for these large templates, taking quite a long time to fully render the page. Once it's done, everything is nice and snappy, but it's like a 20-30 second wait after the wire even on my beefy 5900x.
Chrome seems to handle this just fine.
It's possible that the culprit is a bad polyfill or a Firefox-specific bug in TinyMCE, I haven't put much work into diagnosing it yet beyond verifying that TinyMCE is eating up all the CPU time. For now my planned solution is to just write my own WYSIWYG editor, because TinyMCE ultimately offers a lot more than we actually need, and it was only a stopgap solution to get out a polished MVP. But needless to say, for the first time in years, I found myself spending a non-trivial amount of development time in Chrome. Sadly I've never actually had a client use this app with anything other than Chrome or Safari, so this is naturally a low-priority issue.
Here are instructions of using the profiler with just a few clicks: https://profiler.firefox.com/
For your own mental health, don’t. I was looking for an old article describing how bad the API is, written by one of the authors of a WYSIWYG JS editor, but I can’t find it.
What if you only loaded/initialized the editors when they became visible?
Deleted Comment
Basically it just lets you extend how many roles/accounts you can switch between in the AWS console UI.
Also keep in mind although Firefox containers is made by Mozilla it's a plugin that you have install, which was very counter intuitive when I first wanted to use it.
I leave Safari as my default browser, although I actually use it the least. But I like having the same "default" experience on my desktop and phone. If I am opening a link from Mail.app or punching something into Alfred it will open in Safari. I use some light ad-blocking. I use Chrome for work. I use Google Translate a bit and this works extra well in Chrome. Plus, Google apps and whatnot. Limited ad-blocking because I'm often using ads platforms. I use Firefox for all my intentional/casual browsing. Maximum ad blocking.
- better privacy protections
- not wanting to leave web standards entirely to Google/Apple (for-profit corps)
Brave attempts to address the first, but does little about the second as it uses Blink (i.e. Chrome's engine). Personally, I care a lot more about the second.
They’re not wives, you can have more than one.
It's not a direct apples to apples comparison, but my anecdotal evidence, on Linux, is the opposite. I usually use Firefox on my Linux/X11 box, but every now and again I fire up Chromium and always get the feeling that it's much snappier.
Someone should make an automated Unmozilla’d Firefox that rips out all phone-home and advertising. I’d run that.
Dead Comment
* CPU Usage is extremely higher than in chrome for video call/meeting related websites.
* Font rendering is horrible on a lot of websites. I think this is more fault of the website developers, but it doesn't change the fact that I as end user with Firefox have subpar experience.
* The native OS integration seems very janky, from swipe to go back, to pinch to zoom, something feels off about them.
* I've encountered a lot more websites that didn't quite work smoothly. This is same as one of the points above of web developers being at fault here, but it still doesn't change my experience with FF.
I want to use Firefox, but not if it degrades my experience - which it currently very noticeably does.
> At this point, you might wonder if os_unfair_lock – possibly coupled with the undocumented flags – would be a good fit for your codebase. My answer is likely yes but you’ll have to be careful when using it.
I would hesitate to give this advice. The overwhelming majority of applications on macOS do not have performance profiles like Firefox does. The system allocator (rather than jemalloc) is the right choice for all but very few use cases. There are a vanishingly small number of usecases where using the undocumented flags is appropriate.
The rules are different when you’re a popular browser with an existing relationship with Apple and dozens of smart engineers who can (at least in theory) understand the consequences of using this API, and leverage an existing relationship with Apple to ensure that it doesn’t become a liability in the future as the platform evolves. For pretty much everyone else, this should be nothing more than a “wow, neat” blog post.
I sincerely doubt that Firefox can leverage anything with Apple, or that Firefox engineers have much of a relationship at all with Apple. Who does, really.
I'm not sure it matters though. Many smaller Mac developers have a long history of using private API, and it's largely fine. There's no truly "safe path" with Apple, because Apple does whatever it wants whenever it wants, and I've seen them break "supported" API plenty of times, and leave it in a broken state. But the risks of any given brokenness are small, and you can't predict what will break from year to year, so what can you do except go with what works, and hope for the best.
It's certainly fair to say that the majority of applications on macOS do not have the performance profiles of Firefox, but it's also the case that the majority of applications weren't even using lower level primitives like OSSpinLock in the first place, so replacing it was not a concern.
The target for this comment is developers like you, but those who are less familiar with the platform than you are but of similar import. Those are the ones who will read this and say “wow Firefox says this is how to make my app fast so I should do it!!1!” and what is going to happen is either they’re going to use it wrong, because they aren’t really experts on how locking works, or they’ll copy the code of of Firefox and their app will break in a future OS release while Mozilla will update their code in July.
However those are not suitable for use in the memory allocator, and neither are WebKit's. WebKit uses os_unfair_lock within its memory allocator:
https://github.com/WebKit/WebKit/blob/520379e30f3b2b6d4de995...
And so does Chromium:
https://source.chromium.org/chromium/chromium/src/+/main:bas...
From some Zig code:
To me it has always seemed as a decent strategy, and when working on a cross-platform heavily multi-threaded code base which had a fairly contested hot-spot, Windows performed quite well using just plain critical sections.
[1]: https://learn.microsoft.com/en-us/windows/win32/sync/critica...
App stores allow users a centralized place to both acquire known and verified applications as well as get updates for them. They are a safe place to buy things - Apple is not going to steal your credit card. For developers, they are a convenient place to park your app, without having to manage your own distribution services. And payments is always pain - it's probably the single biggest value add that the app stores cover it for you.
And you can always circumvent it on these platforms. It's just an addition. I'd prefer to get an app on the mac app store if it is there, if it is not then that is fine as well, but will require more digging to verify it's authenticity.
I think the problem is locking us to one app store - because the app store does provide some added functionality (easy of use - one place to go for all apps - security vetting - automated update settings across apps)
App stores are distribution mechanisms and advertisement channels, same value proposition as Spotify compared to shipping your music on your own website.
1. Switching on/off VPN would hamper the connectivity (sometimes only), not sure if this specific to my network
2. Responsiveness is an issue, key type response is slower. I will check if this new version helps.
Thanks FF team for your efforts.
When I disconnect from VPN, Firefox still has the VPN's proxy settings. I have to restart it to refresh Firefox's cached proxy settings. So that means I effectively have to restart Firefox any time I change between VPN and non-VPN.
If that's your problem too, then I don't have a fix for it. I'd love to hear if anybody else does though.
https://addons.mozilla.org/en-US/firefox/addon/switchyomega/
I haven't had an issue with Firefox with that.
Are you doing something nicer than manually flipping location or going into the network settings and turning the proxy on/off?
You could also manually specify a DNS provider like Cloudflare or NextDNS on the personal user for DoH / DoT
A lot of times, I have to close the current tab and open a new one to regain connectivity.
It is my only issue with Firefox on mac, currently.
Huh, now that you say it: I haven't been all that angry at Firefox lately.
I think I also don’t understand the discussion about spinning in kernel space. Doesn’t that require context switches which the article points out have issues? I would have guessed the answer would be to spin a bit in userspace with architecture-specific instructions like pause and then syscall if the lock couldn’t be acquired. Maybe I just don’t really know how syscalls work on a Mac.
I’m also weakly curious why jemalloc needs so much locking anyway? I haven’t thought about this at all so I’m surely missing something but my guess would be allocation from per-thread pools with occasional synchronisation, and that this synchronisation would be too infrequent to have these issues.
Spinning in kernel space does require a transition into the kernel. But, critically, it does not require rescheduling another thread and waiting around, which is even more expensive. The kernel has the context to know what is running and what isn’t, as well as some information on who owns the lock, so it can do a pretty good job here. Spinning in userspace is bad because the thread holding the lock may be parked by the kernel, which means that you’re just spinning for no reason. If you don’t include any special instructions you burn power, and even if you do you don’t benefit from the knowledge the kernel has of whether you should just be scheduled off while waiting anyways.
I'd love to hear from someone with more firsthand knowledge, but from a quick read of the implementation details for jemalloc, it seems there is a balance that has to be struck between lock contention and memory fragmentation. Too few arenas and lock contention slows you down, too many arenas (or enabling thread-specific caches) and the cache misses from fragmentation will slow you down.
the blog post also mentioned that Firefox's jemalloc is highly customized, maybe firefox's specific profile gets value out of a more lock-heavy strategy.
https://jemalloc.net/jemalloc.3.html (see "Implementation Notes")