WebKit代码在资源受限的嵌入式环境下的定制问题
传统的WebKit及Chromium为了性能和丰富的HTML5功能特性而优化,即使是iPhone或Android这样的手机移动设备,其内存也动辄以2G以上计。
那么,当我需要在资源受限的嵌入式环境下运行WebKit,如何进行节省资源的裁剪定制呢?
这里所谓的资源受限,指的就是像车载设备、智能电视这样的终端,CPU通常使用ARM,但主频不高;内存只有512MB以下,虽然也支持OpenGL ES,但能力受限。
首先考虑所谓的“节省资源”,这有2个方面的含义:
1、静态的资源 主要指程序编译出来的二进制文件大小
2、动态的资源 指程序运行时占用的内存大小
静态优化可以采取的措施如下:
1、降低性能,裁剪代码
WebKit很多代码分支很多都是用于处理特殊条件下的优化,可以把这部分优化的分支去除(用条件宏关闭)
比如,完全禁用JavaScriptCore的优化处理,让它退化为一个普通的解释器引擎(jsc目前可能还不能以纯解释器模式运行?)
再如,完全禁用图形渲染硬件加速后端,采取纯软件的绘制代码,同时禁用某些会影响纯软件实现性能的功能,如CSS 3D变换、模式/梯度填充等
2、关闭某些模块
比如比较庞大的svg、xml模块
3、有选择的关闭某些HTML5 API
4、将WebCore/rendering下面的某些渲染功能取消掉,比如border的模式填充
动态优化
1、WebKit或者使用系统内存分配器,或者可使用TCMalloc,这些内存分配器的问题是它们会预先分配一个比较大的堆(内存池),造成不必要的占用
其实可以使用一个最原始的基于双链表的实现(freelist、uselist),这个原始实现在分配大量小对象时可能造成碎片,不过这个问题可以根据实际对象的大小及分配频率进行一些优化
2、重写关于大图片显示的代码
目前的图像解码对于一个大图片都是要分配很大的一块连续内存的,这个其实可以使用tiling切片的思路,拆分为小图片显示,甚至可以把每个像素从rgba32降低到16位
3、关闭任何形式的缓存
网络缓存自不必说,其实最占大头的是字体缓存,不过也可以做一些优化:比如只使用一种字体。
其他
1、使用编译器所能够提供的LTO(链接时优化),将没有被调用的函数代码从生成的二进制文件中去除
WebKit从设计初就没有考虑到资源受限的嵌入式环境下的“节省资源”处理,某些数据结构可能需要重新设计(可能会影响性能),例如:
1、CSS解析模块
不存储中间的解析结果数据(RenderStyle里的XxxData),而是直接存储原始字符串格式的数据,这样每次查询CSS属性的取值都需要重新解析,但的确能够节省大量内存
这里可以考虑一下如何在这种极端的设计下仍然还能够优化性能?
2、不再在内存中分配大量字符串对象(其实内存里的String对象就是外部存储系统文件字节流的缓存而已)
尽管WebKit为字符串对象定义了不同的类型,如AtomicString、CString、String等,但每一种类型都意味着额外的重复存储,可以这么优化:
只保存原始html的输入字节流,其他的字符串对象全部保存为对此输入字节流的(offset, bytesLength)引用
甚至可以更进一步,不保存解码后的Unicode数据,只使用之前的字节数据,实际的字符串操作需要即时做Unicode解码
(不过我怀疑这么做是否会大幅度影响性能?)
如果我们可以假设CPU速度足够快,内存访问速度也还可以,但是内存本身总大小受限,那么上面的2点也许值得考虑。

传统的WebKit及Chromium为了性能和丰富的HTML5功能特性而优化,即使是iPhone或Android这样的手机移动设备,其内存也动辄以2G以上计。
那么,当我需要在资源受限的嵌入式环境下运行WebKit,如何进行节省资源的裁剪定制呢?
这里所谓的资源受限,指的就是像车载设备、智能电视这样的终端,CPU通常使用ARM,但主频不高;内存只有512MB以下,虽然也支持OpenGL ES,但能力受限。
首先考虑所谓的“节省资源”,这有2个方面的含义:
1、静态的资源 主要指程序编译出来的二进制文件大小
2、动态的资源 指程序运行时占用的内存大小
静态优化可以采取的措施如下:
1、降低性能,裁剪代码
WebKit很多代码分支很多都是用于处理特殊条件下的优化,可以把这部分优化的分支去除(用条件宏关闭)
比如,完全禁用JavaScriptCore的优化处理,让它退化为一个普通的解释器引擎(jsc目前可能还不能以纯解释器模式运行?)
再如,完全禁用图形渲染硬件加速后端,采取纯软件的绘制代码,同时禁用某些会影响纯软件实现性能的功能,如CSS 3D变换、模式/梯度填充等
2、关闭某些模块
比如比较庞大的svg、xml模块
3、有选择的关闭某些HTML5 API
4、将WebCore/rendering下面的某些渲染功能取消掉,比如border的模式填充
动态优化
1、WebKit或者使用系统内存分配器,或者可使用TCMalloc,这些内存分配器的问题是它们会预先分配一个比较大的堆(内存池),造成不必要的占用
其实可以使用一个最原始的基于双链表的实现(freelist、uselist),这个原始实现在分配大量小对象时可能造成碎片,不过这个问题可以根据实际对象的大小及分配频率进行一些优化
2、重写关于大图片显示的代码
目前的图像解码对于一个大图片都是要分配很大的一块连续内存的,这个其实可以使用tiling切片的思路,拆分为小图片显示,甚至可以把每个像素从rgba32降低到16位
3、关闭任何形式的缓存
网络缓存自不必说,其实最占大头的是字体缓存,不过也可以做一些优化:比如只使用一种字体。
其他
1、使用编译器所能够提供的LTO(链接时优化),将没有被调用的函数代码从生成的二进制文件中去除
WebKit从设计初就没有考虑到资源受限的嵌入式环境下的“节省资源”处理,某些数据结构可能需要重新设计(可能会影响性能),例如:
1、CSS解析模块
不存储中间的解析结果数据(RenderStyle里的XxxData),而是直接存储原始字符串格式的数据,这样每次查询CSS属性的取值都需要重新解析,但的确能够节省大量内存
这里可以考虑一下如何在这种极端的设计下仍然还能够优化性能?
2、不再在内存中分配大量字符串对象(其实内存里的String对象就是外部存储系统文件字节流的缓存而已)
尽管WebKit为字符串对象定义了不同的类型,如AtomicString、CString、String等,但每一种类型都意味着额外的重复存储,可以这么优化:
只保存原始html的输入字节流,其他的字符串对象全部保存为对此输入字节流的(offset, bytesLength)引用
甚至可以更进一步,不保存解码后的Unicode数据,只使用之前的字节数据,实际的字符串操作需要即时做Unicode解码
(不过我怀疑这么做是否会大幅度影响性能?)
如果我们可以假设CPU速度足够快,内存访问速度也还可以,但是内存本身总大小受限,那么上面的2点也许值得考虑。