zoukankan      html  css  js  c++  java
  • Mac OS X 背后的故事(九)半导体的丰收(上)

    在美国宾夕法尼亚州的东部,有一个风景秀美的城市叫费城。在这个城市诞生了一系列改变世界的奇迹:第一个三权分立的国家——美立坚合众国,就在第五街的路口诞生;举世闻名的费城交响乐团,1900年在市中心的Academy of Music奏响了他们的第一个音符。而写这篇文章时,我正坐在三十四街的宾夕法尼亚大学计算机系的一楼实验室,面前摆放着世界上第一台电子计算机——ENIAC。

    1946年2月14日,ENIAC问世,每秒可运行5000次加法运算或500次乘法运算,面积达170平方米,重约30吨,拉开了计算机处理器革命的序幕。这场革命是各处理器厂商长达数十年的竞赛,而摩尔定律从一开始就准确地预测了这场比赛的走势。根据摩尔定律,同样价格的集成电路上可容纳的晶体管数目,每隔约18个月便会增加一倍,性能也将提升一倍。但事实上,并无法用老路子来保持这个增长速度,因为会遇到包括能耗、散热等各种技术瓶颈。所以每隔几年就会有用来绕过这些瓶颈的新一代产品推出。如采用超纯量(superscala)、指令管线化快取等。这些技术通过一定程度的高效并行来挖掘计算机处理器的速度所能达到的高度,以促使用户更新换代。

    世界上第一台计算机ENIAC,1946年2月14日诞生于宾夕法尼亚大学

    和66年前的ENIAC相比,今天的处理器已有了质的飞越。而21世纪的前十年,我们更是见证了个人计算机处理器的三次重大革命——64位处理器、多核心和高效图形处理器在个人电脑出现。在这样的背景下,乔布斯在2008年WWDC(苹果全球开发者大会)上,宣布下一代Mac操作系统Mac OS X 10.6将被命名为Snow Leopard(雪豹)来适应硬件架构的革新。就在那天下午,Bertrand Serlet在一场开发者内部讲座上透露,和先前两个发行版包含大量的新功能(10.4 Tiger包含150个新功能,10.5 Leopard包含300个新功能)不同,Snow Leopard不含任何新功能,仅是对Leopard中诸多技术的重大更新,以使其在现代架构上更稳定、高效。 在这十年的最后一年,2009年8月28日,苹果发布了Mac OS X 10.6来有效地支持这三项技术,而本文将为读者介绍其对应的三项软件技术——64位架构、Grand Central Dispatch,以及OpenCL。 其他Mac OS X 10.6技术更新,如全新的QuickTime X和跳票的ZFS,有着更复杂的历史背景(以后再为读者介绍)。

    64位架构出现的缘由

    前文提到,根据摩尔定律,同样价格的集成电路上可容纳的晶体管数目,约每隔18个月便会增加一倍,性能也将提升一倍。事实上,存储器的容量增长可能更快,每过15个月就会翻一番。有了更快更强的电脑,可能会让数值计算的科学家们喜出望外,但对普通大众来说,摩尔定律给普通消费者一个假象——如果你觉得1000美元的苹果电脑太贵,那等上18个月就可以用500美元买到同样的电脑。十年前你在用电脑写Word文档,十年后你还在用电脑写Word文档,反正计算机不是耗材,一台电脑只要不坏,就不用去买新的。计算机产业的巨头们自然知道摩尔定律对他们造成的致命打击,因此,一个阴谋被以Intel和Microsoft为首的巨头们构想出来—Intel负责把硬件越做越快,而Microsoft则负责把自己的软件越做越臃肿、越做越慢—至于你信不信,反正我是信的。因此,使用软件、服务等,直接促进计算机产业的消费,使得计算机产业走上可持续发展的道路。这在计算机产业被称为Andy-Bill定律,分别以Intel和Microsoft总裁的名字命名。

    当然,软件公司未必真心欺骗消费者,故意把软件做大做慢——为了实现一个新功能,软件势必会比原先庞大。但现代软件的速度、大小和其增加的功能并不成比例。比如对最终用户来讲,Windows Vista到底比Windows XP多了多少功能呢?可能只有20%~30%。Word 2007对比Word 2003多了多少功能呢?可能也只有20%~30%。但Windows Vista、Word 2007占用的CPU、内存、磁盘空间,却比Windows XP和Word 2003翻了几番。究其原因,为了能赶快把新功能带给用户,我们不惜使用更方便但低效的编程语言(.NET、Java等依赖虚拟机的语言就要比C慢许多,Python等动态语言比C慢的不是一星半点)、快速开发(我们原先处理一个大文本,先分块,一点一点读到内存中,然后把处理完的部分写回磁盘,清空内存;而现在直接把它全读进来处理,开发方便,执行也快)。而用户必须为这些新功能买不成比例的单。64位就是在这个背景下迅速走入寻常百姓家的——程序占用越来越多的内存,而32位的寻址空间已不能满足软件运行的需要了。

    64位 CPU是指CPU内部的通用寄存器的宽度为64bit,支持整数的64bit宽度的算术与逻辑运算。早在1960年代,64位架构便已存在于当时的超级电脑,且早在1990年代,就有以RISC为基础的工作站和伺服器。2003年才以x86-64和64位元PowerPC处理器架构(在此之前是32位元)的形式引入到个人电脑领域。从32位元到64位元架构的改变是一个根本的改变,因为大多数作业系统必须进行全面性修改以取得新架构的优点。

    成功的迁移

    苹果向64位处理器的迁移花了整整6年时间,远长于该公司其他技术的迁移——向Intel的迁移仅用了一年时间,从经典Mac OS到Mac OS X也仅用了三年时间。总而言之,这场迁移是非常成功的:一方面,用户基本无痛苦,老的32位程序在目前最新版的Mac OS X Lion中依然可以完全兼容地执行;另一方面,对开发者而言,基本只需做微小的调整,重新编译程序,而且若干技术如Universal Binary,使他们发布程序非常方便。当然,对于某些大量使用过时技术的公司,如Adobe和Microsoft,这场迁移则要折腾得多。

    这场迁移整整用了四个发行版的时间(10.3至10.6),不同于Windows或Linux,Mac OS X对64位的迁移自下而上,再自上而下。先是内核扩展,逐渐上升至Unix空间,然后上升至用户界面,再上升至整个应用程序生态,最后完成内核的迁移。要提醒读者的是,Mac OS X的32位和64位内核空间与用户空间的分配和实现,和Windows存在本质的区别,但在本期介绍中,我们尽可能少地把Mac OS X 的64位迁移和Windows进行比较,不拘泥于技术细节,对此区别有兴趣的读者,请移步AppleInsider的系列专题

    2003年,苹果发布了其第一款64位计算机工作站Power Mac G5。同期发布的Mac OS X 10.3也因此增加了非常简单的64位支援,于是XNU内核开始支持64位的寄存器和整数计算。但对于用户空间而言,程序可见的地址依然是32位的。程序当然可以使用大于4GB的内存(Power Mac G5最高可达8GB寻址空间),但这要求程序手动地在两个32位内存空间中来回转换。

    两年后,苹果发布了当时最成功的Mac OS X发行版Mac OS X 10.4 Tiger。10.4的内核是革命性的,除了增加对内核并行多线程的支持,它把用户空间可见的地址空间扩展到了64位,因此理论上用户程序可以以64位方式执行。当然,在这个时期,几乎系统内的所有程序,哪怕是内核,依然是32位的。系统中唯一带的64位二进制文件是名为libSystem.dylib的系统库。它是Mac OS X上对C标准和POSIX标准的支持库,由libc、libinfo、libkvm、libm和libpthread五部分组成。但这仅有的libSystem.dylib理论上就能让所有仅使用C标准库和POSIX标准库的程序以64位模式运行。当时,用户对64位的需求较少,主要限于科学计算或图形处理等需要大数组的领域。因此,10.4能较好地满足这部分用户的需求。但如果程序需要调用除BSD Unix以外的系统调用,比如想用Cocoa来画图形界面,那么该程序仅能以32位方式运行了。对于一些需要64位寻址空间的科学计算程序,比如Mathematica,就需要采用一些比较麻烦的做法:用一个进程调用32位的Cocoa画图形界面,用另一个进程调用64位的libSystem来进行运算和Unix系统调用,并用Unix管道或进程间通信的方式管理两个进程间的输入/输出。

    苹果在Mac OS X 10.4发布同期的另一项重要决策是向Intel平台x86及x86_64架构的迁移。为了帮助开发者和用户顺利迁移,苹果正式公布了Universal Binary。Universal Binary 技术是Mach-O二进制文件早就具有的特性,只是在这个场合作为一个商业词汇进行宣传。NeXT时代NeXTSTEP操作系统就支持许多种不同的硬件架构,自然可以要求开发者对每个平台发布一个独立的版本,但这样的分发模式很麻烦,消费者也需要搞清到底购买哪种平台的软件。因此NeXT的Mach内核所支持的Mach-O二进制文件格式引入了一种叫fat binary的特性,说白了就是在一个平台架构上分别交叉编译所有平台的二进制格式文件,然后把每个文件都打包成一个文件。Universal Binary就是指同时打包Intel平台和PowerPC平台的二进制文件。Mac OS X 10.4最终支持四个平台的BSD系统调用——32位Power PC、64位PowerPC、32位 x86和64位x86_64。作为最终用户,无须搞清这些区别,因为使用Universal Binary技术,买回来的软件直接会解出相应平台程序的二进制文件并执行。这是苹果很成功的一步——不像Windows系统中要用不同的路径(\Windows\System、\Windows\System32、\Windows\System64)分别存放不同架构的二进制库,并且用户还需在32位版和64位版之间犹豫不决。

    Mac OS X 10.5 Leopard经过一系列跳票终于在2007年末发布,跳票主要原因是当时苹果投入了大量人力和物力去做iPhone,以至于10.5跳票了整整一年。10.5包含了约300项新功能,而最重要的一项是苹果把对64位的支持带入了Cocoa层面。因此,几乎系统中所有的库都有四个平台的版本。在WWDC上乔布斯亲自向与会者介绍迁移到64位的好处,而能使用更大的内存自然是一项重要优势,程序可以申请更大的内存,把所有数据一并读入内存中操作,而无须分块后来来回回地在内存和磁盘搬运数据。另外,对Intel平台来说,x86架构只有8个寄存器,而x86_64平台有16个寄存器,这也就意味着,对该平台来说,只要重新编译程序,程序就能自由调度比原先翻倍的寄存器数量而无须快取或在内存中来回查找和读写。根据粗略估算,一般涉及大量数值计算的程序会加快一倍。所以他很开心地劝说所有的开发者都迁移到64位架构。

    历时整整6年时间,苹果完成了向64位处理器的迁移,同时这也给苹果提供了良好的清理门户的机会——清理过时的技术和API。

    彻底的清理

    同时,苹果做出了一个大胆的举动——Carbon框架并未出现在这次迁移中。Carbon是Mac OS X诞生之初为了帮助Mac OS开发者把老程序迁移到新的Mac OS X操作系统上所提出的一个兼容API,这套API长得很像经典Mac OS的API,但能够得到Mac OS X平台提供的一切新特性,Adobe、Microsoft等都是通过Carbon把它们经典的Mac OS程序移植到Mac OS X上的。苹果的本意是希望开发者用Carbon迁移老程序,用Cocoa开发新程序,但在Carbon诞生之初,其受关注度远大于Cocoa,据TeXShop开发者Dick Koch回忆,在Mac OS X 刚诞生的开发者大会上,Carbon讲座的教室挤满了人,而Cocoa相关的讲座上听者无几。维护两套雷同的API的代价自然很高,所以砍掉一个是大势所趋。Carbon和Java的热度甚至一度让苹果产生索性把Cocoa或Objective-C砍掉的想法。大量苹果自家的程序如Finder、iTunes、Final Cut、QuickTime等也都是用Carbon写成的。不过在此后由于大量涌现在Mac OS X平台上的新程序都是Cocoa写的,导致Cocoa技术不断走高。2007年的iPhone也完全依赖于Objective-C和Cocoa的一个裁剪版Cocoa Touch。因此在WWDC2006上,苹果在Mas OS X Leopard 10.5的开发预览版中包含了测试版本的64位Carbon库,甚至还有讲座教如何开发64位的Carbon程序。但苹果却在2007年告诉Carbon开发者,他们的程序将不可能再被编译成64位,要做到这点,必需先把程序用Cocoa重写。

    这个突然的决定激怒了很多开发者,尤其是以Microsoft和Adobe这些巨头为代表的公司。Adobe全套的Creative Suite和Microsoft全套的Microsoft Office是很多苹果用户必备的软件,数百万行代码全是用Carbon写的。所以直到今天,除了Adobe Photoshop等少数程序终于在2010年全面移植到Cocoa后做出了64位版,其他大部分程序依然停留在Carbon的32位模式。

    苹果也花了很长时间来重写Finder、FinalCut、iTunes、QuickTime等程序或技术,耗费了大量精力。当Adobe发布64位的Lightroom 2.0时,苹果还在手忙脚乱地重写Aperture。不过公正地讲,长痛不如短痛,砍掉对Carbon的支持能够使苹果把更多精力放在该做的事上,也使得Mac OS X的结构更简洁,并且事实上,64位的迁移为苹果提供一个砍去老API的机遇,哪怕对Cocoa也是。一方面,Cocoa框架中很多类不是使用类似Carbon的API,就是依赖于用Carbon实现(注意,和传统观念不同,Carbon和Cocoa在早期Mac OS X上是相互依赖的,比如菜单NSMenu就使用了Carbon的菜单管理器),这些API在64位得到了彻底清理,QuickTime相关的C接口全被砍去。Cocoa经过很长时间的发展,自然也保留了很多过时的API以保证和原先的产品兼容,而这次机会给苹果足够的理由彻底推翻原先的设计。在Mac OS X 10.5中, Objective-C的运行库libobjc更新到2.0,提供了全新的并发、异常处理、自动内存回收、属性(property)等新机制,其中很多新特性只供64位享用。同时,所有int都被改为NSInteger,Core Graphics中的float都改为CGFloat,以保持API统一,这些都是64位架构上的改动。因此64位迁移给苹果一个很好的清理门户的机会。

    作为相反的例子,这次清理也有不彻底的地方。比如从老版Mac OS中混进来的Keychain库,甚至具有Pascal风格的API,由于没有替代品,它也得到了64位的更新。所以类似keychain这样的库成了现在Mac OS X程序员的噩梦。我每次用到Keychain都有痛不欲生的感觉。

    而2009年发布的Mac OS X 10.6 Snow Leopard则是对64位真正完整的支持。Unix层虽然10.4就提供了64位的libSystem,但所有的Unix用户空间工具包括ls、Python等,以及Xcode中的gcc,也都是以32位二进制的模式发布的。图形界面层,在10.5 Leopard中,虽然整个系统的库都迁移到64位,以32位和64位的混合模式发布,但用户应用程序依然是32位的。只有Chess、Java、Xcode套件等少数程序以64位编译。但在10.6中,基本所有的应用程序都被迁移到64位,不管是Safari、Mail、Dock,还是TextEdit。当然,各种Unix工具包括LLVM、GCC等也都以64位的模式发布。10.6只有四个Carbon程序(Front Row、iTunes、DVD Player以及Grapher)未得到64位升级【2009年查阅,现页面已更新至10.7】。其中, Front Row在Mac OS X 10.7 Lion中被砍掉, iTunes在10.7发布时依然以32位模式发布,在2011年末的更新中才迁至64位。

    为了使应用支持64位,苹果不遗余力地改写了大量代码,Snow Leopard中最重要的重写当属Finder,这个程序自Mac OS X发布以来就一直是一个Carbon程序,并且苹果一直不停地改进它以展示Carbon无所不能。但自从10.5时代苹果下决心砍掉Carbon后,该程序被完整地重写。新的Finder和Carbon版的Finder看上去并没有太大差别,但Finder使用Cocoa重写后,不仅速度更快,而且增加了许多Cocoa新特性,比如加入了更多的Core Animation特效来平滑过渡动画。总之,虽然苹果在10.6期间没有提供太多新功能,但这样大规模的重写,为今后代码的可维护性奠定了良好的基础。

    Mac OS X 10.6发行版也完成了64位化的最后一步——内核的64位化。我们将在下期杂志中和读者仔细讨论。

    作者王越,美国宾夕法尼亚大学计算机系研究生,中国著名TeX开发者,非著名OpenFOAM开发者。

  • 相关阅读:
    JAVAGUI设计步骤
    JAVA接口基础知识总结
    静态关键字static用法。
    JAVA面向对象的多态性
    java封装的概念
    多线程
    关于集合类间的区别
    JAVA——异常
    java——内部类
    Java——接口
  • 原文地址:https://www.cnblogs.com/xust/p/2735430.html
Copyright © 2011-2022 走看看