Runtime API / Function

createFlamoRuntime

创建一个新的 Runtime 控制面,用于配置并管理一组 Instance 的注册表、App 复用、资源池与宿主能力。

使用说明

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 时销毁它。

参数

optionsFlamoRuntimeOptions