使用说明
Runtime 是什么
Runtime 是 Flamo 在宿主应用中的长期运行边界。一个编辑器、画布区域或具有共同生命周期的页面区域,通常对应一个 Runtime。它负责把可持久化的 Artifact 变成可交互内容,并统一管理这一运行域里的资源与对象。
通过 createFlamoRuntime(options),可以配置该运行域使用的 canvas、App 默认参数、组件解析器、宿主服务、模块策略和 ResourcePool。创建之后,Runtime 提供一组完整的控制能力:
- 使用
runtime.create()创建 Instance,并可通过其中的target在创建阶段绑定宿主; - 使用
runtime.mount(target, artifact)创建并挂载新的 Instance; - 使用
runtime.get()/runtime.list()查询当前运行域中的对象; - 使用
runtime.inspect()获取可观测快照; - 使用
runtime.destroy()结束对象生命周期并释放其引用; - 使用
runtime.probeCapabilities()检查当前宿主支持的能力。
Runtime 还决定一组内容如何共享 App、ECS world、渲染循环和资源缓存。它适合由宿主持有,并随着编辑器、画布或页面区域的整体生命周期创建和释放。
mount() 属于 Runtime,不属于返回的 FlamoInstance。如果先调用 runtime.create({ artifact }) 且未提供目标,不能再调用 instance.mount(target);应在创建选项中传入 target,或直接使用 runtime.mount()。
同一个 Runtime 内共享 App 的优势
默认情况下,Runtime 会让其 Instance 共享同一个底层 Flamo App。这个层级复用的是 ECS world、SceneRuntime、渲染循环、Canvas surface 管线和 App 使用的资源池,而不是把所有 Instance 合并成一个实例。
具体收益是:
- 创建多个 Instance 时不需要为每个实例重复初始化 App、ECS world 和渲染循环。
- 相同图片或视频可通过内容寻址 registry 复用已解码、已上传的 GPUTexture,减少重复加载与显存占用。
- App 默认在最后一个 Instance 销毁后继续保活,后续重新挂载可复用已有 world,避免重复初始化并提高 remount 稳定性。
- Instance 仍保留独立的 idMap、selector、props、bindings 和生命周期;共享资源不会让同名节点或交互串到其他实例。
shareApp: false 会让每次 runtime.create() 使用独立 App。只有确实需要独立 ECS world、渲染循环或故障边界时才这样配置。
多个 Runtime 共享 ResourcePool
多个画布需要独立 Runtime/App 时,可以只共享更底层的 ResourcePool:
import { createResourcePool, createFlamoRuntime,} from '@flamo/runtime';
const resourcePool = createResourcePool();
const leftRuntime = createFlamoRuntime({ canvas: leftCanvas, shareApp: false, resourcePool,});
const rightRuntime = createFlamoRuntime({ canvas: rightCanvas, shareApp: false, resourcePool,});这时左右画布拥有独立的 App、ECS world、SceneRuntime、selector 和事件状态,但共同复用:
- 同一次
GPUAdapter/GPUDevice初始化; - 按 hash 缓存的图片解码结果与 GPUTexture;
- 视频元素、视频帧纹理和媒体注册表;
image:、font:、module:、html:等资源引用的解析结果;- 按 Runtime / Instance / source node 记录的资源 retain/release 所有权。
这比“每个画布完整创建一套 GPU 和媒体资源”更省初始化成本与内存,同时又比共享整个 App 提供更强的场景隔离。
外部传入的 ResourcePool 由宿主持有;应在所有使用它的 Runtime 和 Instance 都结束后再调用 resourcePool.destroy()。资源复用会延长缓存存活时间,因此它是在初始化成本、内存驻留和隔离强度之间做出的明确选择。
最小用法
const runtime = createFlamoRuntime();const instance = await runtime.mount(container, artifact);
// 宿主卸载时await runtime.destroy(instance);常见误区
- 不要为了渲染每个组件都新建 Runtime;同一生命周期域的一组 Instance 通常应由同一个 Runtime 管理。
shareApp与resourcePool不是同一层:前者共享 App/world,后者可以在 App/world 隔离时只共享 GPU 与媒体资源。- 不要在仍有 Runtime 使用 ResourcePool 时销毁它。