@fideus-labs/fizarrita (法语)
工人集体加速 get编号 :set 页:1 萨里塔.js ——向工人卸下编码/解码器 @fideus-labs/工人池。 。 。 .
在 Web Workers 的浏览器中运行, 在节点运行 node:worker_threads; 数据
正确的解码工是为你挑选的。 见 节点.js。 。 。 .
安装
pnpm add @fideus-labs/fizarrita @fideus-labs/worker-pool zarrita
快开始
import { WorkerPool } from '@fideus-labs/worker-pool'
import { getWorker, setWorker } from '@fideus-labs/fizarrita'
import * as zarr from 'zarrita'
const pool = new WorkerPool(navigator.hardwareConcurrency ?? 4)
const store = new zarr.FetchStore('https://example.com/data.zarr')
const arr = await zarr.open(store, { kind: 'array' })
try {
// Read — codec decode runs on workers
const chunk = await getWorker(arr, null, { pool })
// Write — codec encode runs on workers
await setWorker(arr, null, chunk, { pool })
} finally {
pool.terminateWorkers()
}
API 密码
getWorker(arr, selection, options)
萨里塔的倒置替换 get从商店取出原始字节
主线,转移给集合工人 编码,然后
组装输出块.
const chunk = await getWorker(arr, [zarr.slice(0, 10)], { pool })
// chunk.data — TypedArray
// chunk.shape — number[]
选项 (单位:千美元)GetWorkerOptions:
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
pool | WorkerPool | 所需经费 | 用于编码操作的工人池 |
workerUrl | string | URL | 内置 | 编码工作脚本的 URL |
opts | StoreOpts | —— 说 | 商店的通过选项 get 方法 |
useSharedArrayBuffer | boolean | false | 在共享箭头缓冲器上分配输出, 并解码到共享优化 |
cache | ChunkCache | —— 说 | 可选解码- 重置缓存以避免冗余解压 |
signal | AbortSignal | —— 说 | 中止读取: 取消飞行中商店获取、 放弃队列解码任务 |
setWorker(arr, selection, value, options)
萨里塔的倒置替换 set。处理部分块更新
在工人身上解码现有的块, 在主线上修改,然后
对工人进行编码.
// Write a full array
await setWorker(arr, null, { data, shape, stride }, { pool })
// Scalar fill
await setWorker(arr, null, 42.0, { pool })
// Partial update
await setWorker(arr, [zarr.slice(2, 8)], newData, { pool })
选项 (单位:千美元)SetWorkerOptions:
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
pool | WorkerPool | 所需经费 | 用于编码操作的工人池 |
workerUrl | string | URL | 内置 | 编码工作脚本的 URL |
useSharedArrayBuffer | boolean | false | 在部分更新时使用共享箭头缓冲器进行中间缓冲 |
signal | AbortSignal | —— 说 | 中止写入: 放下队列的块任务, 取消正在部分更新的块读取 |
像萨里塔的 set,则写入不是交易:块在
信号起火要写.
选择
selection 同一位置列表 zarr.get 采取 -- null,整数,
财务报告和审定财务报表 zarr.slice(...) (其界限可能是: bigint(s) 萨里塔的
zarr.select 从维度名称中构建一个:
// arr.dimensionNames -> ["time", "y", "x"]
const frame = await getWorker(
arr,
zarr.select(arr, { time: 0, y: zarr.slice(0, 256) }),
{ pool },
)
斯卡拉阵列( S)shape: [])读与作相同.
支持的数组
Zarr v3 阵列, 和 v2 阵列通过相同的转换 zarrita 当它被应用时
打开它们:从 dtype, (中文(简体) ), order: "F" 作为转接器, 数字编码cs
zarrita 的过滤器和压缩器 numcodecs. 编码名称,和
fixedscaleoffset 作为 scale_offset + 键 cast_value数据类型
(单位:千美元)float16 运行时间在哪里 Float16Array) (中文(简体) ).
被硬化的数组 (单位:千美元)sharding_indexed)读与作相同.
arr.chunks 是内块形状,所以选择,块缓存和
useSharedArrayBuffer 所有工作 每个内块, 工人解码和
与内置编码器编码内块.
- 读取: 硬度指数是每硬度一次的比对 记住
对于商店的寿命, 每个内块是一个范围请求.
将商店包入
zarr.withRangeCoalescing批次内块 将一个硬化为更少的 HTTP 回合请求。 就像萨里塔一样 存储需求getRange(单位:千美元)FetchStore财务报告和审定财务报表FileSystemStore拥有它;zarr.open拒绝一个没有商店的已磨损阵列. - 写作 - 萨里塔自己的
set拒绝: 将硬体重写为 整个。 书写封面的内接部分在工人身上同时编码; 其余部分从所存储的硬体复制( 仅当一些 (b) 指数被重建(bytes财务报告和审定财务报表crc32c索引编码器; 而硬体是用它最后的任务来完成的 每一个内心 块写触摸是写出, 甚至一个都是填充值。 两个 同时写给同一个艰难的种族, 最后一个胜利者—— 作为两个 同时部分写到一个块。 写作会下降Fizarrita的 记起硬体的索引; zarrita 自己的索引Array记得索引 也没有被告知,所以你应当谨读zarr.get通过新打开的 写入后数组setWorker。 。 。 .
由 Zarrita 商店扩展件包裹的仓库(zarr.withByteCaching, (中文(简体) ),
zarr.withRangeCoalescing, (中文(简体) ), zarr.withConsolidatedMetadata,或者你自己的
zarr.defineStoreExtension工作不变:取出块字节
arr.store 在主线。 阵列扩展( E)zarr.defineArrayExtension, (中文(简体) ),
替换 arr.getChunk,被绕过 – fizarrita 获取并解码
块本身.
错误
失败是Zarrita的结构错误, 所以同样的检查工作
getWorker编号 :setWorker 关于 zarr.get编号 :zarr.set数字 :
try {
await getWorker(arr, selection, { pool })
} catch (e) {
if (zarr.isZarritaError(e, 'CodecPipelineError')) {
// e.codec, e.direction, e.chunkPath — and e.cause, the codec's own error
} else if (zarr.isZarritaError(e, 'UnknownCodecError')) {
// e.codec is not registered in the worker's zarrita registry
} else if (zarr.isZarritaError(e, 'InvalidSelectionError')) {
// out of bounds, wrong rank, zero step
}
}
一个工人内部出现解码错误;工人报告错误,并且是
在调用线条上重建 chunkPath 页:1 内容 cause 携带
原始消息,但不是原始错误对象.
共享对话框
这两种功能都接受 useSharedArrayBuffer: true 额外业绩.
getWorker - 输出键盘由 SharedArrayBuffer。 。 。 .
工人通过
decode_into 协议,取消一个矩阵缓冲器传输和一个
每块主线脚本。 返回的块可以与其他块共享
工人不复制.
setWorker 用于部分更新的中间块缓冲器
SharedArrayBuffer,减少主线程和编码器之间的传输
在解码-修改-编码周期的工人.
所需资源
SharedArrayBuffer 要求使用下列页面:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
实例 :
export default defineConfig({
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
})
如果信头不见了, useSharedArrayBuffer: true 丢入
描述性错误.
取消读取
由景点驱动的消费者不断阅读
旧的瓷砖仍在飞行中。 通过一个 AbortSignal 所以一个废弃的读物
停止耗用资源, 而不是运行到完成 :
const controller = new AbortController()
const read = getWorker(arr, [zarr.slice(0, 256), zarr.slice(0, 256)], {
pool,
signal: controller.signal,
})
// The user panned away — these tiles are stale:
controller.abort()
信号传递到每个块 store.get 呼叫读数,所以存储
(例如:. FetchStore,其选项是 a RequestInit取消
他们的网络要求当它开火。 池上仍然排队的春克任务是
放弃而不是开始, 返回的承诺与
信号的原因。 已经运行在工人身上的解码没有中断——
其结果被抛弃。 共享元数据读取和块形状探测器是
唯一的例外是,他们跑的时候没有它 弹出缓冲。 。 。 .
若为 opts 携带自己的存储层 signal,两者合并:
要么是火灾,要么是抢断, 仍然排队的任务被放弃, 承诺
拒绝任何发射信号的理由。 并行 getWorker
呼叫共享飞行中
以已中止的读取块不受影响- 它重排了块
在自己的信号下.
弹出缓冲
getWorker 接受可选选项 cache 用于存储已解码块。 重复时
调用缓存跳过全部取回并解压,返回缓存
直接在主线上切入 .
任何对象 get(key) 财务报告和审定财务报表 set(key, value) 工程——平地 Map 这是
最简单的选项 :
const cache = new Map()
// First call — fetches, decodes, and caches each chunk
const a = await getWorker(arr, null, { pool, cache })
// Second call — all chunks served from cache, no workers used
const b = await getWorker(arr, null, { pool, cache })
缓存密钥使用格式 store_N:/array/path:c/0/1/2A级 WeakMap- 基于
存储 ID 确保密钥在存储实例中是独一无二的, 因此单个缓存可以
安全地通过多个阵列和存储共享.
阵列元数据读取和块形状探测器被记录
(存储,阵列路径)——两者在一个阵列的一生中都是不可改变的——所以
只有第一个 getWorker 调用数组来触摸商店 。 A 类
重复读取完全从温暖缓存中执行零存储请求 .
同时要求冷阵列共享一个分辨率. 存储选项于 opts
(标题,证书,.)也达到这些内容,只有一个例外:
AbortSignal 只管呼叫的等待 从来不管共享
决议——中止一个呼叫者迅速拒绝,而不使其他呼叫者失败
然后结果仍会变成下一个读数.
LRU / 边框缓存
对于已绑定的内存, 请通过任何执行相同的 LRU 缓存 get编号 :set
接口 :
import { LRUCache } from 'lru-cache'
const cache = new LRUCache({ max: 200 })
const chunk = await getWorker(arr, [zarr.slice(0, 10)], { pool, cache })
当缓冲帮助
如果:
- 重叠选择 例如,在块相间行走的地盘上行走 许多切片。 没有缓存,每个片块都会被解压 这触摸它.
- 重复读取 ——重读一个阵列的同一片区域(拓宽/分区) 在取景器中,重置相框.
- 大型压缩块 ——减压主导一等/一等等,所以 避免它产生巨大的速度.
何时 useSharedArrayBuffer 与 cache,缓存错过使用
标准解码路径(工人通过传输返回已解码块)
块可以存储在缓存中. 快取点击将缓存块复制到
主线程上的共享箭头缓冲输出 。 首个入口的起落架
完全绕过工人的缓存点击来偿还.
ChunkCache 接口
interface ChunkCache {
get(key: string): Chunk<DataType> | undefined
set(key: string, value: Chunk<DataType>): void
}
节点.js
getWorker 财务报告和审定财务报表 setWorker 在没有额外设置的平地节点工作。 包裹
2个编解码工条目 codec-worker.js 用于浏览器和
codec-worker-node.js 页:1 node:worker_threads - 和 createDefaultWorker
在运行时在它们之间选择.
import { WorkerPool } from '@fideus-labs/worker-pool'
import { getWorker, setWorker } from '@fideus-labs/fizarrita'
import * as zarr from 'zarrita'
const store = new Map()
const arr = await zarr.create(zarr.root(store).resolve('/data'), {
shape: [1024, 1024],
chunkShape: [256, 256],
dtype: 'int32',
})
const pool = new WorkerPool(4)
try {
await setWorker(arr, null, 42, { pool })
const chunk = await getWorker(arr, null, { pool })
} finally {
// Required in Node: worker threads hold the event loop open.
pool.terminateWorkers()
}
注释:
- 总是打电话
pool.terminateWorkers()- 否则节点进程将 不离开. useSharedArrayBuffer在节点工作,不需要COOP/COEP头;SharedArrayBuffer无条件提供.- 代码可用性是Zarrita的,不是我们的. 正在工作的zarrita船只
zstd, (中文(简体) ),blosc, (中文(简体) ),lz4,以及bytes执行;gzip, (中文(简体) ),zlib,以及crc32c解码但不编码( 写入失败, 有CodecPipelineError和它一样 显示在zarr.set),除非从numcodecs,在 工人,通过 定制解码器。 。 。 .
工人信件协议
内置编解码器工人处理四种信息类型:
| 请求 | 回应 | 说明 |
|---|---|---|
init | init_ok | 注册编码元数据(每组配置每个工人一次) |
decode | decoded | 解码原始字节, 向后传输解码的 ArrayBuffer |
decode_into | decode_into_ok | 解码并直接写入共享箭头 |
encode | encoded | 编码块数据(C顺序,或 stride ,将编码为字节的字节调回 |
以通常的反应类型回答失败的请求 error页:1
以及——当失败是扎里塔的结构错误之一时——
errorInfo,从中调用线条重建它.
解码器元数据被复制——每个独特的数组配置被发送到一个
工人只有一次,然后以整数缓存 metaId。 。 。 .
自定义解码器工人
要使用定制工人脚本 :
const workerUrl = new URL('./my-codec-worker.js', import.meta.url)
await getWorker(arr, null, { pool, workerUrl })
await setWorker(arr, null, data, { pool, workerUrl })
自己建一个工人 而不是通过一个 workerUrl,使用时
createDefaultWorker(),返回当前运行时间的已准备好的工人:
import { createDefaultWorker } from '@fideus-labs/fizarrita'
const worker = createDefaultWorker()
这两个条目也可作为子路径输出,但它们 劳动者 输入模块,不可导入帮助 ——每人附上一个信息处理器 它被装入的范围。 在主线程上导入它们不会创建 工人:浏览器条目会将其处理器绑入页面,而节点条目 直接抛出。 把它们当作工人的脚本,而不是进口品:
// The specifier resolves to the worker file; it is never imported directly.
const url = import.meta.resolve('@fideus-labs/fizarrita/codec-worker')
await getWorker(arr, null, { pool, workerUrl: url })
两者都是很薄的入站点 handleCodecMessage,则导出为
定制工人可以不重新执行协议而延长协议.