Blink内存缓存存储了什么?

12
除了浏览器缓存之外,浏览器还有其他几种方式来缓存数据。对于Chrome浏览器,渲染引擎 Blink 中有另一个缓存,它将图片、样式、脚本和字体(可能还有更多)存储在内存中。
这个缓存用于对站点的连续导航。从Blink缓存中传递的资源在网络选项卡中标记为(来自内存缓存)。从浏览器缓存中提供的资源标记为(来自磁盘缓存)现在我的问题是,哪些资源存储在此快速缓存中并从中传递? 根据我的测试,差别很大:
  • 直接在HTML中的图像和脚本标签非常有效。
  • 直接在HTML中的样式(链接)标签有时有效。有时它不起作用(在同一浏览器和同一会话中)。
  • 以编程方式插入到HTML中的脚本标签几乎从不起作用。但也有时候它能正常工作。

磁盘缓存和内存缓存的一个重大区别在于与Service Workers一起使用时变得很明显。由内存缓存提供服务的请求无法在Service Worker中被观察到(因为缓存位于Service Worker之前)。由磁盘缓存提供服务的请求通过Service Worker(因为浏览器缓存位于Service Worker后面)。

为了展示这种行为,我建立了一个包含所有资源类型的测试页面:https://dm-clone-optimized.app.baqend.com/

您可以使用顶部的链接浏览网站,并观察其在网络选项卡和控制台中的请求行为。每个页面都加载相同的资源。

经过一段时间的导航(Chrome 70.0.3538.67),我大部分时间都会遇到以下情况:

enter image description here
  • HTML从网络获取
  • 脚本标签scripts.jsscripts2.js来自内存缓存
  • 图像标签logo.png也来自内存缓存
  • 样式链接标签styles.css来自磁盘缓存 :(
  • 通过编程方式添加的脚本标签scripts2.js?id=1也来自磁盘缓存 :(
有时候,我非常幸运,所有内容都从内存缓存中提供:enter image description here 我很想了解 Blink 内存缓存是如何工作的,以及如何调整我的站点以使用适当的缓存控制头来处理所有资源。
---- 编辑 ----
最让我担心的是:为什么动态添加的脚本根本没有被缓存?这对于像require.js这样的框架有明显的影响,因为它们将所有依赖项作为动态添加的脚本标记插入。

据我了解,缓存控制并不能提供影响渲染引擎实现的缓存策略的细粒度级别。除非您想了解 Blink 如何解释 max-age 属性?作为 Web 内容开发人员,您通常不需要关心 Blink 如何管理其缓存(内存 vs 磁盘)。我不确定您是否深入研究过 Blink 文档,但这个演示文稿很有趣:https://docs.google.com/presentation/d/1soWvmqxWuZQ_ZchvPZFgf5frAQBBlq5f2tJTuDDPZI8/edit#slide=id.ge29dfb420_1_450 - user3474985
@user3474985 实际上,Blink 缓存似乎遵守像 max-age 这样的缓存控制指令。至少带有 max-age=0 no-cache no-store 的资源似乎不会被缓存。我想知道的是为什么动态添加的脚本根本不会被缓存(除了一些罕见的时刻)。Yoav Weiss 和 Jake Archibald 似乎也认为这有些奇怪,请参见 Twitter 对话 - Erik
1
我关注这种行为的原因是它对像require.js这样的框架有明显的影响,因为它们将所有依赖项作为动态脚本标签插入。如果JavaScript在商店前端(例如)中成为性能瓶颈,这尤其成为问题。 - Erik
2个回答

2

Blink内存缓存工作原理

Blink有四个内存分配器:PartitionAllocOilpantcmallocsystem allocator

因此,Chrome Blink团队已经从Blink中删除了tcmallocsystem allocators

Blink(PartitionAlloc+Oilpan)是呈现器内存的第二大消费者,在典型情况下占用10-20%的内存,并在Discardable,CC和V8中保留一些内存。

Blink内部的主要内存消耗者为:

  • 大型StringImpls(由JavaScript源代码使用)
  • 共享缓冲区(由资源使用)
  • 向量和哈希表

建议是:“识别对Blink总内存有影响的缓存,并仅在它们上实现purgeMemory()

  • 减小(DOM对象)的大小不会有影响
  • 在大多数情况下,丢弃缓存不会影响

他们正在努力摆脱“DiscardableMemory”项,这将有助于执行像强制“分离所有布局对象”这样的操作,从而释放布局树保留的内存。


2

我认为这是Chrome优化的结果,他们让信息对您更加详细。

文件总是进入磁盘缓存。它们也会进入内存,并很快被清除。

Chrome足够聪明,会在查找磁盘之前询问正在运行的进程是否仍然有它们的加载副本在内存中。这一步具有很高的命中率,因为这些图像/JS正在积极地用于某些操作。

您无法控制Chrome如何管理它们的TTL/内存容量以保持blob热度。Chrome开发团队根据实际硬件容量和系统负载进行了大量的动态调整。

P.S. 如果您要求将您的应用程序保留在内存中,您就会陷入Sun/Adobe邪恶的方式:通过托盘图标/服务使其应用程序DLL保持活跃状态,并减慢其他所有人的速度。

P.P.S. 如果是最终用户可能想要使用的应用程序,请使用Electron并遵循WhatsApp/Slack等构建始终运行的应用程序的方法。


嘿 @DennisC,谢谢你的回答。为了消除误解,我的问题不是关于Blink如何清除条目以管理其内存,而是为什么动态添加的脚本根本不会被缓存(除了一些罕见的情况)。这对像require.js这样的框架有明显的影响,因为它们将所有依赖项作为动态脚本标签插入。 - Erik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接