Chrome的差量升级Courgette

Windows客户端做程序的升级是一件比较复杂的事情。不像移动端,有专门的移动商店用来安装和更新程序,Windows客户端程序升级需要自己制作安装包,放到服务器上供用户下载,后续还需要提供升级服务。由于用户操作不可预知性和用户环境的复杂,安装跟升级都会发生各种异常而失败。迄今为止Windows上也没有一个好的程序安装、升级、卸载框架,这不得不说是Windows开发的悲哀。 而且目前程序的安装包越来越大了,动辄几十兆,用户下载安装包需要很长的时间,这也是导致安装升级成功率低的一个原因。所以,安装升级包越小越好。对于这个问题,有两个解决思路: 程序功能模块化,把代码编译到不同的dll里面。如果某个模块有修改,就只需要升级相应的dll就行了。 找出旧版本和要升级的新版本文件的差异,把差异文件发给客户端。客户端根据旧版本和差异文件还原出新版本。 对于第一种方案,优点是实现起来比较简单,我之前的老东家360很多产品就是用的这种方案。这个方案的缺点也很多: 把功能模块化,这个升级粒度依然有点大,有些dll可能只是修改了几行代码就需要升级这个几兆的dll文件。 如果底层模块的接口改了,那么调用它的上层模块都需要修改,这就导致升级会涉及到很多文件。 如果模块代码划分不清或者有一些隐式的逻辑依赖,这种dll升级可能引入难以觉察的bug,甚至会导致程序崩溃。 第二种方案已经有了bsdiff了。但是对于Widnows客户端程序,依然存在很大的挑战。因为C++这种需要编译的代码,充满了内部地址引用,一些指令直接包含其他指令的地址或者位移,几行代码的修改就会导致许多地址值的改变,结果导致最终生成的二进制文件差异很大。 Google的Chrome开发团队特地为C++这种需要代码编译的程序开发了一种叫做Courgette的差异算法。原理是先把可执行的二进制程序进行反汇编,找到那些内部的地址指针,把它们替换成一个符号,然后再用常规的办法生成差异文件。 下面是常规的bsdiff升级: 这个是Courgette升级: 不得不佩服,这是个绝妙的思路。没有对C++、编译器、汇编、PE文件格式深厚了解的人,是无法设计出如此精妙的方案。 Chrome团队还有一个数据的对比: Full... Read More | Share it now!