跳到主要内容

缓存

缓存 API 的职责是跟踪已创建的体数据、管理内存占用, 并在试图分配的数据会超出应用设定的上限时提醒宿主应用。

这个模块负责影像和体数据的缓存。

缓存由两个主要部分构成:影像所用的易失区,以及体数据所用的非易失区。 整个缓存共享一块分配好的内存,例如 1GB,由影像和体数据共同使用。

  • 单张二维影像是易失的,会被新进入缓存的影像替换掉。
  • 分配体数据时,缓存会把该体数据用到的影像标记为非易失,直到你释放这份体数据。

缓存的工具函数​

有若干工具函数可以用来管理缓存。

  • isCacheable:Cache API 提供的众多工具函数之一。 在发起体数据或影像的请求之前,可以用它检查是否还有足够的空闲空间。
  • purgeCache:删除缓存中的全部影像和体数据。
  • decacheIfNecessaryUntilBytesAvailable:根据请求的字节数, 在必要时清理缓存。

缓存优化​

缓存中的所有数据实际上都是 image 对象。当你请求一份体数据时, 我们按需把该体数据所需的影像传给 GPU,任何时候都不会把体数据的体素数据存进缓存。 如果你需要访问体数据的体素数据,可以通过 VoxelManager 类来访问。

如果你确实需要一份体数据的完整体素数据,可以用 VoxelManager 类的 .getCompleteScalarDataArray() 方法取得。

这项变化是在 Cornerstone3D 2.x 中引入的,属于新的「以影像为单位」的整体思路, 目标是提升性能、降低内存占用、并提供更高效的数据访问—— 对大型数据集尤其明显。

新方案还有这些好处:

  1. 唯一可信来源

    • 以前:数据同时存在于影像缓存和体数据缓存中,会带来同步问题。
    • 现在:只有一个可信来源——影像缓存。
    • 好处:堆栈分割与体数据分割之间的同步得到改善。
  2. 新的体数据创建方式

    • 现在一切都以影像的形式加载。
    • 体数据的流式加载是逐张影像进行的。
    • 只有影像会被缓存进影像缓存。
    • 做体数据渲染时,数据直接从影像缓存进入 GPU,绕过 CPU 端的标量数据。
    • 好处:不再需要在 CPU 中保留标量数据,内存占用下降,性能提升。
  3. 面向工具的 VoxelManager

    • 充当索引与标量数据之间的中间层。
    • 提供从 IJK 到索引的映射器。
    • 在不创建标量数据的前提下取得所需信息。
    • 逐张影像分别处理。
    • 好处:高效支持那些需要在 CPU 中拿到像素数据的工具。
  4. 处理非影像类体数据

    • 没有影像的体数据(例如 NIfTI)会被切分并转换为堆栈形式。
    • 这让非影像类体数据也能适配新的「以影像为单位」的方案。
  5. 优化后的缓存机制

    • 数据以其原生格式存储,而不再一律缓存为 float32。
    • 更新 GPU 纹理时再即时转换为所需格式。
    • 好处:内存占用下降,省掉了不必要的数据类型转换。
  6. 去掉 SharedArrayBuffer

    • 移除了对 SharedArrayBuffer 的依赖。
    • 每张解码后的影像直接以正确的尺寸和位置进入 GPU 的三维纹理。
    • 好处:安全限制减少,Web Worker 的实现得以简化。