缓存
缓存 API 的职责是跟踪已创建的体数据、管理内存占用, 并在试图分配的数据会超出应用设定的上限时提醒宿主应用。
这个模块负责影像和体数据的缓存。
缓存由两个主要部分构成:影像所用的易失区,以及体数据所用的非易失区。 整个缓存共享一块分配好的内存,例如 1GB,由影像和体数据共同使用。
- 单张二维影像是易失的,会被新进入缓存的影像替换掉。
- 分配体数据时,缓存会把该体数据用到的影像标记为非易失,直到你释放这份体数据。
缓存的工具函数
有若干工具函数可以用来管理缓存。
- isCacheable:
CacheAPI 提供的众多工具函数之一。 在发起体数据或影像的请求之前,可以用它检查是否还有足够的空闲空间。 - purgeCache:删除缓存中的全部影像和体数据。
- decacheIfNecessaryUntilBytesAvailable:根据请求的字节数, 在必要时清理缓存。
缓存优化
缓存中的所有数据实际上都是 image 对象。当你请求一份体数据时,
我们按需把该体数据所需的影像传给 GPU,任何时候都不会把体数据的体素数据存进缓存。
如果你需要访问体数据的体素数据,可以通过 VoxelManager 类来访问。
如果你确实需要一份体数据的完整体素数据,可以用 VoxelManager 类的
.getCompleteScalarDataArray() 方法取得。
这项变化是在 Cornerstone3D 2.x 中引入的,属于新的「以影像为单位」的整体思路,
目标是提升性能、降低内存占用、并提供更高效的数据访问——
对大型数据集尤其明显。
新方案还有这些好处:
-
唯一可信来源
- 以前:数据同时存在于影像缓存和体数据缓存中,会带来同步问题。
- 现在:只有一个可信来源——影像缓存。
- 好处:堆栈分割与体数据分割之间的同步得到改善。
-
新的体数据创建方式
- 现在一切都以影像的形式加载。
- 体数据的流式加载是逐张影像进行的。
- 只有影像会被缓存进影像缓存。
- 做体数据渲染时,数据直接从影像缓存进入 GPU,绕过 CPU 端的标量数据。
- 好处:不再需要在 CPU 中保留标量数据,内存占用下降,性能提升。
-
面向工具的 VoxelManager
- 充当索引与标量数据之间的中间层。
- 提供从 IJK 到索引的映射器。
- 在不创建标量数据的前提下取得所需信息。
- 逐张影像分别处理。
- 好处:高效支持那些需要在 CPU 中拿到像素数据的工具。
-
处理非影像类体数据
- 没有影像的体数据(例如 NIfTI)会被切分并转换为堆栈形式。
- 这让非影像类体数据也能适配新的「以影像为单位」的方案。
-
优化后的缓存机制
- 数据以其原生格式存储,而不再一律缓存为 float32。
- 更新 GPU 纹理时再即时转换为所需格式。
- 好处:内存占用下降,省掉了不必要的数据类型转换。
-
去掉 SharedArrayBuffer
- 移除了对 SharedArrayBuffer 的依赖。
- 每张解码后的影像直接以正确的尺寸和位置进入 GPU 的三维纹理。
- 好处:安全限制减少,Web Worker 的实现得以简化。