内存检查器简介

Kim-Anh Tran
Kim-Anh Tran

本文介绍了 Chrome 91 中的内存检查器。它可让您检查 ArrayBuffer、TypedArray、DataView 和 Wasm 内存。

简介

有没有想过要了解 ArrayBuffer 中的数据?在内存检查器之前,开发者工具只能用来了解 ArrayBuffers 的有限信息。在调试会话期间,通过 Scope 视图进行的检查仅限于查看数组缓冲区内单个值的列表,因此难以理解整体数据。例如,在下面的示例中,Scope 视图将缓冲区显示为可展开的数组范围:

开发者工具中的作用域视图

导航到缓冲区内的特定范围是一个痛点,需要用户向下滚动才能最终到达该索引。但是,即使导航到某个位置很简单,但这种实际“检查”值的方式也很麻烦:很难判断这些数字的含义。inspecting特别是,如果不应将其解释为单个字节,而应解释为 32 位整数,该怎么办?

使用内存检查器检查值

内存检查器

在 Chrome 91 中,我们引入了内存检查器,用于检查数组缓冲区。您之前可能见过查看二进制数据的内存检查工具,这些工具在网格中显示二进制内容及其地址,并提供不同的底层值解释方法。这就是内存检查器带给您的功能。现在,您可以使用内存检查器查看内容、浏览内容,并选择用于解读当前值的类型。它会直接在字节旁边显示 ASCII 值,并允许用户选择其他字节序。请参阅下面的内存检查器的实际运行:

想试试吗?如需了解如何打开内存检查器并查看数组缓冲区(或 TypedArray、DataView 或 Wasm Memory)以及有关如何使用它的更多信息,请参阅有关内存检查器的文档。请尝试使用这些玩具示例(适用于 JS、Wasm 和 C++)。

设计内存检查器

在本部分中,我们将了解如何使用 Web 组件设计内存检查器,还会展示我们的设计目标之一以及实现方式。如果您想了解更多信息,请参阅我们关于内存检查器的设计文档

您可能已经看到了我们的 Migrate to Web Components 博文,Jack 在其中发布了关于如何使用 Web 组件构建界面组件的内部指南。改用 Web 组件与内存检查器的工作相符,因此,我们决定试用这一新系统。下图显示了我们为创建内存检查器而构建的组件(请注意,我们在内部将其称为线性内存检查器):

Web 组件

LinearMemoryInspector 组件是父组件,用于组合构建内存检查器中所有元素的子组件。基本上,它接受一个 Uint8Array 和一个 address,并且在每一项更改时,它都会将数据传播到其子项,从而触发重新渲染。LinearMemoryInspector 本身会渲染三个子组件:

  1. LinearMemoryViewer(显示值),
  2. LinearMemoryNavigator(允许导航),以及
  3. LinearMemoryValueInterpreter(显示基础数据的不同类型解释)。

后者本身是父组件,用于渲染 ValueInterpreterDisplay(显示值)和 ValueInterpreterSettings(选择要在显示屏中显示的类型)。

每个组件都旨在仅代表界面的一个小组件,以便在需要时重复使用组件。每当在组件上设置新数据时,系统都会触发重新渲染,显示在该组件上设置的数据所反映的变化。下面是一个使用组件的工作流示例,在该示例中,用户通过更改地址栏中的地址,设置新数据会触发更新;在本例中,用户是要查看的地址:

组件示意图

LinearMemoryInspector 将自己添加为 LinearMemoryNavigator 上的监听器。addressChanged 函数将通过 address-changed 事件触发。当用户正在修改地址输入时,此操作会立即发出上述事件,以便调用 addressChanged 函数。现在,此函数会在内部保存地址,并使用 data(address, ..) setter 更新其子组件。子组件会在内部保存地址并重新渲染其视图,从而显示该特定地址的内容。

设计目标:使性能和内存消耗与缓冲区大小无关

在设计内存检查器时,我们考虑到内存检查器的性能应该与缓冲区大小无关。

如上一部分所示,LinearMemoryInspector 组件接受 UInt8Array 来渲染值。同时,我们希望确保内存检查器不需要保留整个数据,因为内存检查器仅显示部分数据(例如,Wasm 内存最多可有 4GB,我们不希望在内存检查器中存储 4GB 的数据)。

因此,为了确保内存检查器的速度和内存消耗独立于我们显示的实际缓冲区,我们让 LinearMemoryInspector 组件仅保留原始缓冲区的子范围。

为此,LinearMemoryInspector 首先需要再获取两个参数:memoryOffsetouterMemoryLengthmemoryOffset 指示偏移,即传递的 Uint8Array 的起始位置,是呈现正确数据地址所必需的。outerMemoryLength 是原始缓冲区的长度,需要它才能了解可以显示的范围:

缓存空间

有了这些信息,我们就可以确保仍可像以前一样渲染同一个视图(address 周围的内容),而无需实际获得所有数据。那么,如果请求了属于不同范围内的不同地址,该怎么办?在这种情况下,LinearMemoryInspector 会触发 RequestMemoryEvent,以更新当前保留的范围;示例如下所示:

事件触发器流程图

在此示例中,用户浏览内存页面(内存检查器使用分页功能显示数据块),这会触发 PageNavigationEvent,而后者本身会触发 RequestMemoryEvent。该事件会开始提取新范围,然后通过设置数据将其传播到 LinearMemoryInspector 组件。因此,我们会显示新提取的数据。

哦,你知道吗?您甚至可以检查 Wasm 和 C/C++ 代码中的内存

内存检查器不仅适用于 JavaScript 中的 ArrayBuffers,还可用于检查 C/C++ 引用/指针所指向的 Wasm 内存和内存(使用我们的 DWARF 扩展 - 如果您还没有试过,试一试吧!)请参阅此处,了解如何使用新型工具调试 WebAssembly。对内存检查器在 Web 上对 C++ 进行原生调试的实际运用的简要介绍:

使用 C++ 检查内存

总结

本文介绍了内存检查器,并展示了其设计概述。我们希望内存检查器能够帮助您了解 ArrayBuffer 发生了什么 :-)。如果您有改进建议,请告诉我们并提交错误

下载预览渠道

您可以考虑将 Chrome Canary 版Dev 版Beta 版用作默认开发浏览器。通过这些预览渠道,您可以使用最新的开发者工具功能,测试先进的网络平台 API,并在用户采取行动之前发现网站上的问题!

与 Chrome 开发者工具团队联系

使用以下选项讨论博文中的新功能和变化,或讨论与开发者工具有关的任何其他内容。

  • 通过 crbug.com 提交建议或反馈。
  • 使用开发者工具中的更多选项   了解详情   > Help > Report a DevTools issues来报告开发者工具问题。
  • 发推文:@ChromeDevTools
  • 请在 YouTube 视频或“开发者工具提示”YouTube 视频中留言说明“开发者工具的新变化”。