[QQ 主窗口业务模块的拆解]
此外,其他静态资源(如 SVG、base64 图像)在加载时也会占用不少内存,所以我们采取了按需加载的策略:只在可见时加载,不可见时主动销毁和回收。
[svg 及 base64 资源的 string 内存占用]
为了提升执行效率和代码保护的目的,我们将 JS 代码转成了字节码。尽管跳过了源码编译,直接将字节码交给 V8 执行,但在程序报错还原堆栈等运行时步骤中,V8 仍然会引用源码字符串。为了去掉这份源码,我们使用和源码等长的空格来占位,但通过 devtool 检查发现这些空格字符串仍会占用不少内存空间。最终,我们采取修改和移除 V8 对源码字符串引用的方式,彻底解决了源码字符串的内存占用问题。
- 图片资源
QQ 作为一款 IM 工具,会涉及到大量的图片收发。然而,图片的渲染会占用相当大的内存。举个例子,一张分辨率为 4000 x 2750 的图片,结合设备屏幕像素和聊天区设计尺寸,只需渲染宽度为 567 像素的分辨率图像即可清晰展示。如果以宽度为 4000 像素的分辨率渲染,理论上两者位图所占用的内存大小差距可达 50 倍,并且还会因为渲染带来性能损失。
[图片尺寸对内存影响举例]
在聊天消息列表中的大部分图片仅仅起到预览作用,缩略图渲染就满足了需要。而仅仅在用户真正打开图片查看器放大查看时,才会需要用原图渲染。
实测在聊天中多张不同大尺寸分辨率图片在展示时,渲染进程和 GPU 进程的内存占用有着明显差别。在收发图片时,我们会根据屏幕设备信息和计算展示区域所需实际渲染分辨率,当原图分辨率超出计算所需值,则先调用压缩服务进行图片压缩,生成渲染所需分辨率的缩略图,并在聊天区域进行渲染上屏。在这个策略的优化下,一般聊天图片场景测试下来,使用缩略图比原图约有 30M ~ 50M 的内存优化。