主题:【原创】漫谈浏览器大战 -- (构架篇) -- Highway
最近工作之余稍有闲暇,于是就跟踪了一下最近IT方面的热点新闻。感觉着现在最火爆的两个战场就是手机OS和新一代的浏览器了。可惜我于手机知之甚少,只好避开这个话题谈谈浏览器了。
其实就浏览器而言,我也是业余,也就是自己在家里的PC上鼓捣几下,再结合一点专业上的common sense,如是而已。
浏览器这个领域原先是Netscape Navigator的天下(大家还记着吗),后来微软看着Netscape一夜蹿红怒不可遏,调兵遣将推出免费的IE。经过几个回合的较量,Navigator不敌IE,落草成了寇。再后呢,IE一统天下,市场份额超过了90%。一旦垄断形成,微软就再也没有前进的动力了。所以在很长的一段时间里浏览器这个领域基本上是死水一潭,没有任何创新。
真正意义上打响反IE第一枪的应该算是Firefox了,自推出以后不断的攻城略地从IE的手里抢市场。从技术上看,Firefox还是有一定建树的。首先文件很小,下载和安装都很快。另外,程序质量很高,比当时的IE更快捷更安全。还有,Firefox上的Add-on非常丰富,极大的增强和扩展了Firefox的功能。最后还应该指出的是Firefox支持其他OS,比如说Linux。
眼看着浏览器市场从一手遮天就演变到两强争霸了。没想到Google又半路杀出,非要来个Threesome。现在呢,除了这三巨头抢镜以外,苹果的Sarafi和Opera也搅了进来要分一杯羹。所以最近一段时间每个把星期就有一款浏览器推出新版本,并都会大言不惭的宣布是“天下第一快”。
如果仔细一点看的话,就会发现这下一代浏览器争夺的主战场有三个
1)浏览器平台的构架
2)JavaScript虚拟机
3)图形图像的硬件加速
这第一篇呢,就说说新一代浏览器在结构方面的变化。(由于时间有限,所以只能就最有代表性的IE, FF和Chrome来说了,其他浏览器就不赘述了)
新一代的浏览器,清一色的采用了所谓的多进程构架(Multi-process Architecture)。网上的朋友们都常说是Google的Chrome领风气之先。但事实上呢,IE8的Beta版是最早采用这一构架上市的浏览器,从时间上看比Chrome还要早一些。所以呢Chrome首创这一构架的说法有些谬赞了。
有人会问了,怎么一下子大家都玩“多进程构架”了,早干嘛去了?原先的单进程构架怎么了?
早先的浏览器呢,都算是一个“程序”,所以都是传统的“单进程多线程”设计。也就是从任务管理器上看,只有一个进程(当然你可以启动多个浏览器了搞出来多个进程,那不是我们要讨论的问题)。浏览器内部呢,有很多的线程(thread),它们各司其职一同完成复杂的任务。这种设计线路中规中矩,程序开销小,效率高,没有什么不对的地方。
问题出在了“人民群众日益提高的文化物质要求”上。现在的浏览器已经不是一个传统意义上的“程序”了,已经演化成了一个“平台”。浏览器上搭载了无穷多的add-on,plug-in等等。人民群众要在浏览器上看新闻,听广播,点高清视频,玩3D游戏。。。
除了浏览器的任务变得复杂以外,人们使用浏览器的习惯也变了很多。浏览器上开十个八个Tab同时光顾数家网站已经是家常便饭,并且可能浏览器开了就不带关的,除非是出了问题。
开发浏览器的程序员们都渐渐的认识到,面对这样的任务和要求,原先的单进程构架已经不再适用了。原因很简单。因为单进程构架所以的东西都在一个进程里运行,一个地方出问题可能就会使整个浏览器全部歇菜。浏览器Vendor不管多么严格的控制程序质量,多么苦心积虑的进行测试,还是不能解决这一问题。因为浏览器面对的一个“Open ended world”,你永远无法控制第三方的add-on或是plug-in。这些程序如果出了问题,马上就会波及浏览器。
于是乎,多进程的构架就成为了不二之选。说到底,这种构架的核心就是把浏览器的各大功能块分开,运行在各自的进程里面。一个地方出了问题只会是局部的影响,不会造成整个系统的崩溃。现在的操作系统(Windows, Linux, Mac OS)中各个进程都运行在“保护模式”中,一个进程出了问题操作系统会将其的危害控制在该进程之内,不会对其他进程造成影响。这是浏览器采用多进程构架的基本前提。
这种构架为什么以前不用呢?因为这种构架要比单一进程的那种程序复杂很多。多个进程间的通信要解决好,并且要把开销压缩到最小。就现在的技术水平而言,这个问题已不再是什么大问题了。另外,现在大多的计算机都装配有多个CPU(多核),内存也都比较大,多个线程一起运行的硬件资源也不再是一个制约因素了。
虽然在战略上各个公司所见略同,但是在战术实施上还是相差甚远的。Google的Chrome看起来似乎革命最彻底,FF好像只是现有技术的一点点改良,而微软的IE呢,则是另辟蹊径,又搞了一套。
先看最简单的Firefox.
FF把所有的东西还是留在了主进程内。所以当你启动FF的时候还只是一个进程。当进入到一个网站的时候,如果网站比较简单,那么FF自己就料理了,不会产生任何新的进程。如果这个网站要求Plug-in的支持,比如说Flash,那么FF就生成一个进程(叫做plugin-container.exe),在这个进程里运行Plug-in。如果你又开一个Tab去了又一家网站并且这个网站也需要Flash,那么FF就会共用现有的这个plugin-container为两家网站的网页提供Flash服务。所以说呢,FF的进程数量很好计算,那就是一个主进程 + 零到多个个plugin-container。plugin-container的数量取决于运行的Plug-in的种类有多少。
"C:\Program Files (x86)\Mozilla Firefox 4.0 Beta 7\plugin-container.exe" --channel=2572.bd74660.1358250153 "C:\Windows\SysWOW64\Macromed\Flash\NPSWF32.dll" "Mozilla.Firefox.4.0b7" -omnijar C:\Program Files (x86)\Mozilla Firefox 4.0 Beta 7\omni.jar 2572 \\.\pipe\gecko-crash-server-pipe.2572 plugin
有趣的是如果你离开了或是关闭那些需要plug-in的网站,FF并不销毁plugin-container进程。这呢,算是程序设计中一个常见的手段,就是你一旦使用了某个功能的话,那么很可能你还会再次使用。所以呢,那个plugin-container就给你留着,下回来的时候就是现成的,省事儿不是。但是呢,这种设计也有问题,因为plugin-container的数量只增加不减少,对用户而言,FF的内存越占越多。最后不得不把它干掉从新再来。
好,再来看Chrome
Chrome的做法是一个主进程(称为浏览器进程,就是我们看到的东西),1到N个渲染进程(Renderer进程),0-N个Plug-in进程(多少种plug-in就需要多少个plug-in进程,这点和FF一样),0-N个add-on进程(如果你的Chrome有3个add-on,那么就会多出三个相应的线程),一些服务进程(比如新的GPU process, Rundll32进程)。
对细节感兴趣的朋友,可以用Chrome自带的Task Manager去看看Chrome工作时界面之下后台进程生生灭灭的过程,很有意思。Google的这款浏览器就像一个茶馆一样,门帘永远在哪儿(主进程),客人们(Renderer进程)进进出出换了一茬又一茬。
Chrome的这种设计有两个突出的优越性。一是浏览器职能划分的很细,每一个功能体都在自己的进程中,一个进程的问题影响只是局部性的。第二,由于Renderer进程不停的产生销毁,所以即使程序有memory leak或是memory fragmentation也不要紧,因为过不多久进程就走人了,新进程又会从头再来,一切都是崭新的。
有网上的大拿说,Google的进程模式是Per process per site,不是Per process per tab。其实这句话之对了一半。比说你你到西西河来,Chrome马上生成一个Renderer进程来负责这个网站的Render工作(包括JavaScript的运行)。你点击几个link多出几个Tab来,Chrome并没有多出新的进程来。看起来那些大拿的话是对的。但是如果你手工增加一个Tab并敲入西西河的地址,只时候Chrome就会忘记已有的这个西西河Renderer进程,而重新在来一个(见下图)。
和FF不同的是,如果一种plug-in没人用的话,Chrome会保留它一会儿。如果过了这个时间段还是idle,那么Chrome就将它回收了,如果在保留期间有什么网站需要这种plug-in了,那么就延长它的寿命让它继续工作。
另外Chrome9.0 Beta版在运行Plug-in进程的时候,多了一个Rundll32进程.
C:\Windows\system32\rundll32.exe C:\Users\Somebody\AppData\Local\Google\Chrome\APPLIC~1\90597~1.19\gcswf32.dll,BrokerMain browser=chrome。
这个进程感觉是在主进程和plug-in进程间起什么沟通作用的,但现在的Chrome 8版本没这个东西。另外Chrome会不知在什么时候冒出一个叫做GPU process的进程来。感觉是用GPU来做硬件加速用的,但是并没感觉到任何的不同,它的激活机制我还没有搞清楚。所以这个还有待于进一步观察。
OK,最后来看IE
IE的进程结构比较不直观。从外观上看,有些像Chrome的Per process per site(和Chrome一样也不是那么严格)。但是呢,IE不把Plug-in或是Add-on拿出去。除了主进程以外就是Renderer进程了,只有两种类型,而不是Chrome那样的五种类型。这个Renderer进程除了html, CSS, JavaScript任务之外,Add-on和plug-in的程序也在其中。所以说是一个heavy-duty的Renderer。
和Chrome不同的一点是,IE并不是急于创建或是销毁Renderer进程,它试图重新利用他们。比如你当前是在西西河,如果你在address bar输入另外一个网站的地址离开西西河到别的网站的话,IE会重用当前这个Renderer进程。而Chrome呢,是重新为新的网站生成一个新的Renderer进程,然后马上销毁西西河的这个Renderer进程。
看到这里大家肯定有些晕了,不禁会问“你罗哩叭嗦的说了半天,到底哪种方案最好?”
这个很难说了,要看情况。比如说现在正是2012年伦敦奥运会,你开了三个Tab同时看三场比赛(Tab可以扯到桌面上铺开来看)。一个是中国转播的乒乓球,一个是美国转播的篮球,还有一个英国转播的足球。每个网页上呢是Flash转播的高清视频,另外还有HTML5技术提供的网友实时评论和场外花絮等等。
比方说,英国方面转播的足球出了问题,造成了Flash崩溃。那么用FF的用户和Chrome一样,什么图像都没了(因为Flash进程是共用的)。但是三场球的实时评论和场外花絮还能看得到。IE用户呢,情况不太一样,乒乓球和篮球还能看道视频,实时评论和场外花絮也完全正常,但是足球那个TAB就全歇菜了。
再比方说,美国网站HTML5提供的场外花絮部分出了问题,那么FF用户最惨,整个FF歇菜了,什么都没了。Chrome和IE的用户一样,乒乓球和足球还看着很好的,只不过是篮球那个Tab宕掉了。因为FF是用主进程来处理HTML5的,Chrome和IE都是独立的Renderer进程处理HTML5,出了问题之影响那一个具体的Process,别的Tab一点没事儿。
就我个人而言,有这么几点看法
1)FF的保护机理太过简单了。主线程任务太重,那里面一出问题整个浏览器就宕了。另外,Plug-in process重来不回收也是一个问题。
2)Chrome的进程显然太多了。如果你装了七八个个Add-on,再去几个网站的话,那么整个进程数可能就是十好几个了。对于那些内存少并且less powerful的机器可能就会是一个问题了。不知道在手机平台上Chrome浏览器是不是也用的同样的策略。
3)IE的想法不错,想把进程数量压缩在一个适当的范围内,不给OS太多麻烦。但是不把plug-in和add-on从Renderer进程分离出去,就每个Tab而言,保护程度和可靠性就自然下降了。在实践中的具体效果还有待于检验。
三种浏览器的新一代Beta版本我都用过,似乎Chrome给end-user的感觉最好。那么多进程间的通讯效果很好,进程不停的生成和销毁也没有任何停顿的感觉,界面上始终很流畅,很少有滞后感。(Chrome的程序员们本来开始是要用微软的COM技术来进行进程间通讯的,但发现COM不能满足他们对Async通讯的要求,于是就改用named pipe。虽然麻烦了一点,但看起来效果很不错。不过呢,在Linux平台上,又变成了Socket,不知道有什么原因。)
==============================================
待续。。。
本帖一共被 2 帖 引用 (帖内工具实现)
WebKit2是开源的Rendering Engine,被Google的Chrome和苹果的Safari采用(还有很多其他公司的产品)。
就现在的Chrome而言,每个Renderer进程都含有一个Webkit Engine。问题是如果下一代WebKit自己就变成多进程的哈,那和浏览器是怎么个协助关系呢?难道WebKit2会变成一种Service?这个问题我也很好奇。
Best源码剖析 based on Chrome 1.0(too old)
can't input chinese for a while
I have been using Opera 2 years before FF.
Just do not use IE when I have a choice.
根据内存的大小,标签页对应的进程数会有个上限。但是扩展的进程不受这个限制。
讲一个听来的故事(未经证实)。
一老哥从学校毕业找到一份微软个程序员工作,高兴的无可无不可的。上班以后被分配到IE Team。等把source code check out以后,这老哥当场就晕了。一堆补丁补在另外一堆补丁上,在十几层补丁之外,程序原先是干嘛已经模糊不可考了。每个人接到任务以后,根本就从根上找问题,就是在不定层上再加一个补丁而已。。。
几个月后,这老哥实在没法干了,辞职了是。
微软富可敌国,手下程序员以万计。IE糟糕成这个鬼样子,真是shame啊!
到Google的网站下载10个popular add-on(FF很多用户都有十几个add-on的,所以这不算是过分的要求),然后重启动Chrome,什么地方也不要去,这时候按Shift+Esc打开Chrome的Task Manager。虽然你什么也还没干,哪儿也没去,Chrome已经有12个Process在运行了。
是不是有些多了!
in chrome/browser/renderer_host/render_process_host.cc
// Defines the maximum number of renderer processes according to the
// amount of installed memory as reported by the OS. The table
// values are calculated by assuming that you want the renderers to
// use half of the installed ram and assuming that each tab uses
// ~40MB, however the curve is not linear but piecewise linear with
// interleaved slopes of 3 and 2.
// If you modify this table you need to adjust browser\browser_uitest.cc
// to match the expected number of processes.
static const size_t kMaxRenderersByRamTier[] = {
3, // less than 256MB
6, // 256MB
9, // 512MB
12, // 768MB
14, // 1024MB
18, // 1280MB
20, // 1536MB
22, // 1792MB
24, // 2048MB
26, // 2304MB
29, // 2560MB
32, // 2816MB
35, // 3072MB
38, // 3328MB
40 // 3584MB
};
static size_t max_count = 0;
if (!max_count) {
size_t memory_tier = base::SysInfo::AmountOfPhysicalMemoryMB() / 256;
if (memory_tier >= arraysize(kMaxRenderersByRamTier))
max_count = chrome::kMaxRendererProcessCount;
else
max_count = kMaxRenderersByRamTier[memory_tier];
}
return max_count;
}
但是标签页的进程数是有上限的。
其实我觉得可以把经过认证的扩展放到同一个进程里面,不过貌似google目前还不准备做这个
将向最少消耗资源方面去,flash太耗资源啦
不支持ACTIVEX.
送花。注:送花、宝推可能得宝 关闭
送花成功,可取消。有效送花赞扬。
参数变化,作者,声望:1;铢钱:0。你,乐善:1;铢钱:-1。本帖花:1
人民群众都还在用Windows XP/2000,并且都永远用Admin Account上网玩。一个漏洞被敌人逮着,那就等以把整个机器拱手交出了。所以那时极容易中招。
从Vista起,IE开始运行在非Admin模式下,如果IE要安装什么东西或者对系统进行更改,操作系统会给你一个对话框,如果你说Yes的话,OS就Elevate IE Process privilege,让你把安装完成。现在的Win7也是这个机理,不过是做的smooth一点。提供这种方法,问题缓解了不少!(我试过几个Linux版本,也有类似的做法)