你们觉得作为一个前端,想去了解浏览器整个的渲染过程和执行过程而去学 C++有必要吗?

2016-02-04 11:37:43 +08:00
 coffeedeveloper

好奇的是两方面。

而这些内容也只能通过网络上的一些文章去了解,只能说不甚理解。或者说不能透彻理解。
你们觉得特意去学 C++会不会显得矫情?

如果真的要去学了,要到什么样的一个级别才能够看得懂浏览器相关的一些代码呢?

11670 次点击
所在节点    程序员
78 条回复
keithsliu
2016-02-05 10:09:28 +08:00
这大概就跟学编译原理差不多吧
libook
2016-02-05 11:27:31 +08:00
没啥不好的,就是个性价比问题,如果你有余力还有兴趣还是个 Geek 可以看呀,但要是想速成的话这个方法可能就不合适了吧。
secondwtq
2016-02-05 11:51:24 +08:00
@jukka Web 前端的核心部分,还真跟 OpenGL 关系不大。
OpenGL 是一个 GPU 3D 绘图的 API ,而前端渲染主要涉及的是 2D 矢量绘图,如果你只是搞游戏的话,对矢量绘图可能不是很了解。
简单来说, GPU 不适合 2D 矢量绘图。

游戏(尤其是追求画面效果的 3D 单机游戏)的 rendering 部分的最大目标之一是用最少的硬件资源得到最好的即时渲染效果,这个“好”往往是和“真实”相对应的,聚焦于灯光、贴图等方面,利用的图元是点、面等。而矢量图中,最重要的图元是 Path (有点像 PS 里面钢笔画出来的那玩意, SVG 里面也有涉及),对于填充、线型、曲率等细节的正确性要求较高,同时还存在一个文字排版的问题(这个倒是和游戏沾点边,因为 3D 里面到处都是的贴图无法直接解决游戏 UI 文字渲染的问题)。

剩下的事情很简单,假如要用 GPU 渲染一个无填充矢量圆环路径,用单个四边面表示的话,那是对像素填充率的浪费,如果利用 3D 建模中的手段,大量面片拟合的话,且不论效果好不好,效率又成了问题。
wizardforcel
2016-02-05 12:22:33 +08:00
@secondwtq opengl 不支持 2d 绘图? opengl 取决于平台调用 gdi 或者 x11 进行 2d 绘图。

webgl 的 api 是 opengl es 的子集, opengl es 的 api 又是 opengl 的子集,你怎么能说没关系呢?
secondwtq
2016-02-05 12:25:31 +08:00
@jukka

cont.
据我所知,现代浏览器引擎主要的绘图工作是委托给 Cairo , CoreGraphics , Skia 这样的 2D 绘图引擎的。如果一般人要从零开始写这样一个绘图引擎,也应该主要使用 CPU 算法(根据我有限的 CG 知识,类似的算法也会在 GPU 底层被应用)。我上面所列举出的库,可能在实现细节中利用了 GPU 的 3D 加速,但是这部分内容和楼主的目的距离就太远了。不同的硬件,不同的 OS ,可能使用不同的渲染引擎,不同的渲染方式,我觉得这不是楼主想要的东西。

关于利用 GPU 进行 2D 渲染的问题,可以看一下这个项目 https://github.com/memononen/nanovg ,非常精致的一个库。不过在功能上好像依然没办法和 Cairo 这样高大全的项目相比。学术界也有一摞的 paper ,然而我还没有见到过大规模实际应用的详细信息。顺便, Khronos 是有矢量绘图 API 标准 OpenVG 的,但是目前的硬件实现好像并不能达到 universal 的程度(据说移动 GPU 有实现,桌面端的话, NVIDIA 在 OpenGL 上面做了一个扩展 NV_path_rendering ,并且做了一堆的广告)。

不过另一方面, Web 前端中是有 Hardware Acceleration 和 OpenGL 的概念的。这里可以和大家分享一下我的理解(主要来源于 WebKit 引擎, Apple 官方 repo ):

* WebGL 。这个很直接,就是调用 GL 的 API 绘图,不过 WebGL 提供的 API 是 GLES 的(在 Win 里面可能被 ANGEL 转换掉了)。
* Canvas 。可以理解为 Cairo 等绘图引擎的接口直接暴露给了 JS 。灵活性高(理论上所有用其他元素能画出来的东西都能画出来,其他元素画不出来的照样画不出来),效率不大好说,但是最后还是由绘图引擎进行实际的绘图。
* Composition 。概念上类似于基于 Sprite 的 2D 游戏,就是将某些元素单独渲染到 GPU 贴图上,再渲染到页面中,目的是在动画发生时无需使用 2D 绘图引擎重绘该部分。当然有一个假定前提就是动画过程中该部分内容不会发生改变,因为根据以上所述, GPU 在绘图过程中扮演的角色是有限的,更准确的说,其能做的所有事情就是 play with the sprite ,面片的透明度、颜色、 transform , etc. 这就是熟悉 CSS 的同学们喜闻乐见的 translate/scale/rotate3d, opacity 等属性的“硬件加速”。
不过需要注意的是这也不是必须的,因为基本都是 2D 引擎可以模拟出来的东西,编译时 FLAG 关掉,就可以 fallback 到 2D 的渲染模式。

如果有做 iOS 的同学的话,可以打个比方:浏览器中核心绘图引擎的作用类似于 CoreGraphics , OpenGL 的作用类似于 CoreAnimation ,当然有可能 CoreAnimation 的底层就是 OpenGL 。
secondwtq
2016-02-05 12:31:24 +08:00
@wizardforcel

把范围限制在 现代 OpenGL 的 Core Profile 里面,如何 正确的实现 2D Vector 绘图?

WebGL 的问题 45L 解释的很清楚,不过是将不同类型的调用委托给不同的 API 。
并且我所讨论的是浏览器绘图工作中 dominant 的部分,我们现在日常所浏览的页面中,和 WebGL 沾上边的有几个?倒是 Composition 到处都是。
wizardforcel
2016-02-05 12:44:33 +08:00
后面那条涉及到编译了。 v8 就是 c++写的,所以学 c++就能看懂源码了。

但如果你不想搞得这么复杂,可以尝试实现 c 语言的子集,或者 basic 。你可以搜索《自制 /手写编译器》来找这类教程。只是练手的话,不必非得用 c++来写,用 java 写也行,不过大多数教程都是 c 或者 c++写的,最好还是看看。

也可以用 flex 和 yacc 这种工具来快速生成(就像一些 lab 那样),但我觉得还是手写更能理解其原理。
wizardoz
2016-02-05 14:06:36 +08:00
不是应该跟着标准走吗?陷入到某种具体的实现应该是不靠谱的。
techmoe
2016-02-05 14:06:45 +08:00
有条件尽量吧,适当了解一些原理对于性能优化总会有好处的,但是过度分析就不用了
我是做 php 后端的,我就想有时间分析一下 php 的运行原理之类的
joyee
2016-02-05 14:45:00 +08:00
有没有必要看个人吧,如果平时只是撸业务的,那恐怕没有太大必要,不过多了解实现并且(不可避免地)多翻标准对处理兼容性问题有一定好处。如果是做数据可视化或者做基础库 /框架的,会比较有用,因为优化的需求会比较多,而任何领域的优化都需要足够的底层知识作为基础。

至于专门学 C++ 是不是显得矫情……关键要看楼主计算机基础如何,这些东西说白了也就是大型软件项目而已,如果计算机基础不行(图形学、编译原理、计算机网络等),光看 C++ 是没有用的,还是会一头雾水,还不如先补基础。另外不能说不需要学 C++,因为这些引擎通常含有大量 C++ 技巧(自己实现的智能指针,元编程 etc.),即使你相应的基础知识很熟,要想真的读懂代码也还是要对 C++ 有足够了解。

另外渲染引擎和 JavaScript 引擎是两个次元的东西,前者代码量一般是后者十倍以上,而且对应的标准长度大概是后者的…………百倍以上?前者主要是绘制的计算和 DOM 的实现,大概对于普通前端来说比较上层的那些东西是可以直接开始看的(无非就是把标准里的要求实现出来而已,对着 W3C 和 WHATWG 的标准翻即可),但是里面一些细节(比如 HTML/CSS parser )可以先跳过,具备了足够基础后再来看也无妨。另外最底层的绘制细节一般都交给了 Cairo 之类的图形库,所以没有图形学相关知识的话也可以先当成黑盒子跳过……

JavaScript 引擎的话,如果楼主有足够的编译原理基础又不想跑太偏的话,也是可以直接看的吧……(愿意跑偏一点的可以看看 Lua 的实现这种,相似之处不少,而且相对简单得多)。但是如果 lexer 啊递归下降的 parser 啊 SSA 啊 JIT 这些都不知道是啥的话,来看 V8 之类的引擎肯定会一头雾水的……最起码也得能看懂 ECMAScript 的标准里的文法吧?如果发现看不懂的话,可能还是先去学学编译原理合适些……
joyee
2016-02-05 14:57:30 +08:00
还有我觉得楼主似乎应该搞清楚一个浏览器的架构先……比如不要把 V8 和 Chakra 归成 “浏览器内核”?要知道在 Google 啊 M$ 啊之类的地方,做 JavaScript 引擎的团队通常也是跟浏览器团队分开的,有不同的组织和 leader ,而且后者一般人多得多…… JavaScript 引擎团队更多的是需要对编程语言和高级语言虚拟机有深入了解的人,浏览器团队一般收的人会多元化一些,因为浏览器是个更加庞大、涉及更多领域的项目。而且通常 JavaScript 引擎不止为浏览器服务( Node.js , M$ 的 UWP 等),所以他们需要让这个引擎能够嵌入到非浏览器环境去,自然不能跟浏览器耦合太重。举个栗子来说,早期的 V8 团队都跑去搞 dart 了,而早期的 IE 团队在 M$ 高层不重视 IE 之后很多都跑去搞 WPF 了,大概就能体会到两者技能树的不同了吧……
secondwtq
2016-02-05 15:23:33 +08:00
@joyee 据我了解, JS 引擎主要重心是优化(至于 ES6 新特性的实现什么的就不是很清楚了),这也是现代编译器工程的重点。比如 WebKit 的 JSC 引擎就从最开始的 tree 解释器,发展到 bytecode 解释器,再到现在的 LLInt - Method JIT - DFG - FTL 架构,轮子一点没少造。

不过传统上 JS 引擎确实被认为是“浏览器内核”的重头戏。我最早认识 Chrome 好像也是看到 V8 跑分比较吊,感觉在很多人眼中 Layout engine 完全被无视的样子。
secondwtq
2016-02-05 15:37:11 +08:00
楼主如果去看 Compiler 前端的东西的话,我觉得作用是有助于理解语言中一些语法设计和坑。不过我发觉现在一个现象是,一些教科书之类的东西偏向于讲解静态语言,实际遇到的许多项目则是动态语言。这个地方 VM 优化比前端的分量要重很多,我倒是没有太大兴趣,但是这也是楼主研究的空间。对于后端这部分,我感觉楼主大致了解一下的话,可以更深入地理解一些 JS 对象、属性、闭包、函数调用等方面的效率问题,当然这些和所针对的引擎有很大关系。
joyee
2016-02-05 15:54:22 +08:00
@secondwtq

我的意思是,要看懂 JS 引擎,起码得具备基本的编译原理知识,否则光是编译器前端就已经看不下去了,更不要提后端的优化。但是具备了基本的编译原理知识,起码可以看懂 JIT 以外的大部分东西。目前各个 JavaScript 引擎都是解释器+ JIT 编译器的架构了,包括 V8 这个编译器忠实信徒都为资源有限的设备搞出了 ignition , Chakra 做跨平台移植也是先不管 JIT ,将解释器移植起来再说。所以可以先看懂前端+解释器+GC 的部分,再去深入研究 JIT ,因为后者起码还得对汇编和计算机组成原理有足够的了解才能向下看,恐怕对于前端来说跑得更偏了……

不过和 layout engine 相比,显然 JavaScript 引擎更有趣吧(更像一个 big clean problem ,虽然跟其他语言比一点都不 clean ……), layout engine 感觉就是在跟 W3C 和后面那成山成海的 spec 搏斗,搏斗的同时还要在一个庞大无比的代码山里做性能优化,看起来就枯燥的多……

JavaScript 引擎们反倒更像是普通的高级语言引擎,何况脱离浏览器的使用场景也不少了,能从其他语言的实现里借鉴的东西也很多,不少搞 JavaScript 引擎的人以前都是搞 Java 啊 C# 啊的实现出身的。如果有其他高级语言实现的经验,切换到 JavaScript 的次元相对来说要容易一些……(除了要适应一下各种反人类反优化的语言设计……)
jukka
2016-02-05 16:24:11 +08:00
@secondwtq

感谢回复。:)
本人不是 web 出生,不太了解前端的机制,臆测了一些表示抱歉。
bk201
2016-02-05 16:33:01 +08:00
那你是不是顺带把承载浏览器的操作系统也研究一下?我觉得做什么需要什么再去学什么。胡乱学习基本没几天你就忘了。
vanxining
2016-02-05 17:05:14 +08:00
学 C++是值得的,但我觉得没有动力不大可能看得懂 JS 引擎的代码。难点不是 C++,而是它本身的理论基础一般人不会有接触。
wizardforcel
2016-02-05 19:41:03 +08:00
@bk201 我反而是觉得编译啊,图形啊, system 这些东西国内搞的公司太少,当兴趣研究的人也太少,教程也少,这是不正常的,因为任何一个对计算机有兴趣的人都不满足仅仅调用 api 。前端我不评论,我也没写过几次,后端整天写 curd 我都觉得烦。
keyanzhang
2016-02-05 19:45:13 +08:00
Khlieb
2016-02-05 19:52:53 +08:00
如果能知道浏览器执行过程所用到的各种库能事半功倍

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/255348

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX