将Firefox移植到Apple Silicon

2021-01-21 01:59:31

去年年底发布的基于Apple Silicon的Macs引起了一连串的新闻报道,并对该机器的性能产生了一些惊喜。这篇文章详细介绍了一些有关将Firefox移植为在这些CPU上本机运行的经验的背景信息。

我们将从Mac过渡的背景知识入手,并在继续介绍Universal Binaries概念之前,概述需要了解新架构的Firefox内部组件。

然后,我们将说明DRM / EME如何在新平台上工作,谈论我们在macOS Big Sur上的经验,并讨论我们必须处理的各种更新程序问题。我们将以该发行版结束,并对即将进行的其他各种改进进行概述。

业界一直在猜测苹果将其Mac产品线改为使用ARM CPU。早在2013年,苹果就将他们在iPhone中放入的定制ARM芯片称为“桌面级”设计。

尽管这一说法最初引起了一些怀疑,但在2018年底,计算机硬件杂志AnandTech公布了在iPhone XS上运行行业标准SPEC基准测试的结果,表明即使反映现实桌面用例的工作负载也达到了桌面芯片性能,并且这样做可以显着提高电源效率。这给了我们一些警告,苹果可能准备在不久的将来开始向ARM体系结构过渡。

从Mozillla的平台团队的角度来看,在macOS上进行这种架构更改的一个特别令人感兴趣的领域是Firefox对macOS API的使用。 Firefox和Gecko的起源可以追溯到Netscape代码库,该库在1994年就已经支持Mac。

尽管不断更新,但Firefox仍使用多种macOS API,以跟随Mac多年来的发展(Carbon,Cocoa,HIITheme,Quartz等)。

苹果公司通常会保留它们-毕竟代码已经存在并且可以正常工作-甚至在行为发生变化的某些地方甚至增加了兼容性垫片。但是他们不愿永远保持兼容性,事实上,它们已经取消了先前的macOS Catalina中的32位支持,这对依赖此功能的应用程序(包括许多游戏)产生了影响。

因此,我们担心并不是所有API仍会在新架构上受支持,因此我们不得不进入并在短时间内重写一些小部件,工具箱或主题代码。

根据上述基准的性能和苹果的历史发布时间表,平台团队在3月份估计“ macOS 10.16”可能会在2020年9月或2020年10月左右出现,并且存在很大的风险,可能需要更改API才能添加在计划中已考虑到ARM支持。

2020年6月22日,苹果公司确认将开始将其Mac硬件转移到他们自己的ARM芯片(称为Apple Silicon)上。他们还确认,这些机器将配备Intel x64仿真器(Rosetta 2)并支持iOS应用。

后者导致Mozilla的平台团队对新型Mac是否具有触摸屏产生了猜测。尽管我们曾经(现在仍然)准备好支持它,但至少最终第一批基于Apple Silicon的Mac最终并没有使用它。

在宣布过渡的同时,苹果还宣布了开发人员过渡套件(DTK)的推出,该套件实质上是在Mac Mini外壳中包含iPad Pro的芯片。苹果公司没有分享的是确切的最终机器何时上市。

根据DTK上市的时间以及苹果暗示它将在“到今年年底”的暗示,我们猜测这可能是圣诞节假期之前的事。

回顾过去,我们注意到Apple始终能够在宣布硬件后立即提供可用的硬件,因此我们认为下一次计划发布的日期都应视为发布日期。

当计划于11月10日(比我们的最初估计要早一个月)发布新公告时,我们将其作为发货日期。确实,苹果确实在一周后的11月17日交付了第一批硬件。

在支持新硬件所需的所有工作中,将Firefox移植到64位ARM架构实际上并不是我们要做的事情:多年来,我们在Android和Linux上都支持64位ARM。

我们避免在2019年末之前发布64位Android版本,因为在此之前,我们的JavaScript JIT尚未针对64位ARM进行完全优化,因此生成的64位版本将比32位版本慢。

浏览器也不需要能够在手机上使用超过4GB的内存!在2019年,我们发布了第一个适用于Windows的64位ARM版本的Firefox版本,这为我们提供了一些额外的经验,这正是我们现在面临的努力。

到目前为止,尽管Windows on ARM硬件未能赶上我们的用户,但人们对Apple过渡的期望却大不相同。正如第一部分所述,不仅有充分理由期望硬件性能具有突破性。

苹果公司明确表示,他们将更换整个产品线,而不是发布单个设备作为“感觉”。最重要的是,他们在Mac上成功进行架构转换方面有着良好的记录。

因此,在代码库中已经有64位ARM支持的情况下,第一步工作是遍历所有Firefox代码,依赖项和各种第三方构建系统,以查看它们是否正确处理了Mac可能具有的新颖思想。内部装有ARM芯片。

其次,我们需要适应和修复Firefox代码库中处理低级调用约定的各个部分,尤其是JavaScript和C ++(以及现在的Rust)部分之间的接口。

尤其是防锈。 Firefox依赖于Rust代码,我们需要一个可运行的Rust编译器来构建浏览器。尽管Apple Silicon对Rust的支持正在进行中,但直到8月中旬才有了功能编译器的构建,这限制了Firefox可能取得的进展。

一旦编译器开始工作,就需要对我们依赖的所有Rust板条箱进行类似的练习。需要更新编译器以及依赖某些板条箱依赖确切的编译器版本,尤其是涉及SIMD支持的部件,最终会在以后困扰我们,因为这很难将Apple Silicon支持向前推到早期版本的Firefox,而没有可能影响其他平台。

一个重要的决定是要为基于Intel和ARM的Mac生产单独的版本,还是要生成将两个版本捆绑在一起并在运行时选择正确版本的Universal Binaries。制作通用二进制文件稍微复杂一些,但是我们可以使用现有的工具,其历史可以追溯到Apple支持32位和64位二进制文​​件(可以进行修改)的时间。

它极大地简化了用户的工作-没有下载错误版本的风险-并意味着我们的下载页面和某些本地化等基础架构可以保持不变。

主要缺点是安装程序的大小显着增加,不仅对于ARM用户而且对于Intel用户而言。由于这只会影响初始安装,并且用户通常会通过小得多的更新获得新版本,因此我们认为这是可以接受的缺点,因此可以按照此方法进行操作。

虽然我们可以将Firefox的开源部分自己移植到64位ARM,但Netflix和其他一些视频流服务(例如Hulu,Disney +或Amazon Prime)要求使用封闭源,专有DRM软件对视频进行解码。

如果用户访问了这样的站点,Firefox将自动下载并安装这样的专有EME / CDM模块。这给我们带来了一个问题,因为我们将依赖那些第三方供应商来发布这些解码器的ARM64版本。

我们没有承诺此类更新的发布日期,即使我们这样做,也无法保证它们会在Apple Silicon硬件的未知发布日期之前。随着大量用户使用浏览器在线观看视频,这为本地Apple Silicon版本提供了潜在的突破。

我们最终利用了一种技术,该技术也用于ARM版本的Firefox上的Windows。 DRM视频解码器已经在单独的过程中执行,因此我们可以将用户系统中的专有代码沙盒化。

如果我们强制该解码过程在仿真下运行,我们将能够使用现有的Intel x64解码器模块并使它们与本机运行的主浏览器进行通信。

要使它起作用,有一些陷阱:因为加载Google Widevine DRM模块本身的过程取决于某些运行时库,所以我们也需要这些库的Intel x64副本。

幸运的是,由于通用二进制文件包含两个版本的Firefox,我们能够直接从应用程序捆绑包中将其提取。

其次,Apple实际上并未将其预装的Rosetta 2仿真器交付到Apple Silicon计算机上,但当用户尝试运行Intel应用程序时会触发其安装。

因此,尽管实际上很可能在用户的系统上安装了Rosetta,但我们不能总是这样。触发Rosetta的安装以编程方式起作用,但是我们的一些同事发现很难做到这一点,因此我们在第一个发行版中放弃了这样做,而是转而将遇到相关错误的人员推荐给支持文章。 。

macOS Big Sur Betas独立于Apple Silicon硬件而来,使我们能够更早地了解兼容性故事。令我们欣慰的是,我们不弃用我们所依赖的API,任何向后兼容性问题或缺少垫片都限于小型外观问题,而这些问题通常我们可以很快解决。其他具有类似旧代码库的开源项目并不那么幸运。

尽管Apple尝试通过在使用旧版SDK构建的应用中返回旧版本号来缓解该问题,但将版本号从10.x升至11.0(某种程度上可以预测)在我们的代码和依赖UA嗅探的外部网站中均产生了错误。

将更新的Firefox应用程序包推送给用户-现在是支持两种类型的Apple硬件的通用二进制文件,而不是以前的仅Intel x64-显示出更多的复杂性。

在更新过程中,更新磁盘上的文件后,Firefox将重新启动其自身的更新版本。 Apple Silicon上任何在Intel x64仿真下运行并启动另一个进程的应用程序也会导致该进程在仿真下启动。

因此,当在仿真下运行的旧版Firefox 83启动具有本机支持的新Firefox 84时,它将不会启动新的本机二进制文件,但最终也迫使其也在仿真下运行,至少直到应用程序完全重新启动为止。

尽管我们为此开发了一种变通方法,但我们认为发布日期之前并未对其进行足够的边际收益测试,最终只是添加了发行说明来解决此问题。

更令人担忧的是,用户报告说某些防病毒软件将我们的所有Universal Binaries标记为恶意软件,并在更新到来时破坏了Firefox的安装。

该软件正在使用机器学习技术,并且大概观察到我们组合的Universal Binaries看起来与以前从未见过的其他合法软件完全不同。

通过常规支持渠道与供应商联系的尝试均未成功,因此我们最终搜索了LinkedIn,并设法找到了负责核心防病毒检测的工程师。

他们立即了解了问题的严重性,并采取了迅速的措施来提供修复程序,从而为该产品的用户避免了灾难。值得注意的是,如果没有最后的努力,我们将被无限期地禁止发行本地Apple Silicon版本。

当防病毒软件和浏览器不相处时,这并不是浏览器制造商第一次对反病毒供应商的激励动机不满感到愤怒。

将Firefox的发布时间表与Apple的预计发布日期进行比较,意味着我们的Firefox 83(计划于11月17日发布)与发布硬件的可用性保持一致。

最好在第一批生产机器到达客户后就宣布稳定版本的本机支持,但这也意味着它将在真实硬件上完全未经测试。

我们决定在这里保持保守,并保持对Firefox 84 beta(与Firefox 83当天发布)的最初支持,这给我们和用户提供了时间来评估产品在实际Apple Silicon硬件上的稳定性。 。

尽管有些失望,因为它是Nightly中第一个宣布本机支持的人,但最终还是稍微延迟了稳定版本,但其他浏览器供应商在交付有效版本时遇到的困难支持了我们的决定。 2020年12月15日,当84 beta发布到Firefox 84版本中时,具有本地Apple Silicon支持的Firefox进入了更广阔的世界。

尽管大多数Apple Silicon基准测试表明,Rosetta仿真对性能的影响通常很小,并且可以预期应用程序以本机性能的70-80%运行,但是在测试本机Firefox版本时,我们看到了更大的收益,包括性能翻倍在某些关键基准上,启动速度惊人地提高了2.5倍。

这种更快启动的合理解释可能是Firefox本身的许多部分都是用网络自己的语言(JavaScript,CSS和HTML)编写的,因此将JavaScript JIT用于其自身的许多功能。

启动时,JIT必须将JavaScript转换为机器代码,而在仿真下运行时,这通常是非常快速的操作,Rosetta则必须将此JIT生成的机器代码转换为另一体系结构的机器代码。

苹果公司推出了一个翻译缓存,它可能会为大多数应用程序完全消除这种开销,但不适用于JIT输出的代码。使用本机版本,完全避免了第二种翻译,我们回到了一个快速的浏览器。

随着最初的发布,我们可以并且将对Apple Silicon版本进行许多进一步的改进,其中一些将已经在Firefox 85中提供。

首先,我们必须在初始版本中禁用WebRender,因为它在Apple Silicon的第一个Big Sur版本中触发了图形驱动程序错误。现在,这些问题已经解决,并且我们已经在最终的硬件上验证了WebRender,我们已经重新启用它,它将在85个版本中发布。

其次,Firefox当前在64位ARM上将基线编译器用于WebAssembly。有一个名为Cranelift的更快的优化编译器可在Firefox Nightly上进行测试,并且在几周之内,我们预计将完成我们自己的优化编译器Ion的64位ARM端口,这很可能会成为新的默认编译器。

Apple Silicon芯片是首批采用异构设计并具有独特性能和效率核心的台式机芯片之一。我们正在对大部分核心线程和线程池体系结构进行修订,以更好地处理区别,提高效率,并最终能够在效率内核上安排对性能要求不高的任务。

最后,我们要清理和更新旧版macOS绘图API的用法,并在某些情况下完全删除自定义绘图代码。预期这将有助于解决暗模式支持中的一些突出问题,因为传统的macOS API根本不支持它,并且必须通过更新的API获取颜色值。这也将消除我们对折旧的担心!

我们希望您喜欢Firefox团队如何经历Apple Silicon过渡的内在看法,并且我们希望在来年将macOS上的Firefox体验推向更高的水平。

感谢Mike Hommey和Haik Aftandilian对这个职位的大量投入。他们还完成了此处描述的许多工程工作。 Andrew Overholt,Sylvestre Ledru和Selena Deckelmann提供了进一步的编辑建议。