跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

使用指南

应用样式、组合镶嵌,并在生产环境中运行 async-geotiff。

围绕应用最常组合的能力提供任务导向指南。

1 - 样式与波段计算

使用 Raster Style 3.0 JSON 与 Q3 输入配置栅格样式。

样式输入使用 raster-style = "=0.4.0" SDK,协议版本为 3.0,需要 Rust 1.92。 SDK 负责结构和语义校验,适配器再检查本渲染器支持的能力。未知字段、重复单值参数和 未实现能力均报错。下列能力适用于 Tiler::tile 和 MosaicTiler::tile,不代表完整规范的后端认证。

Rust 输入

use async_geotiff::style::TileStyle;

let style = TileStyle::from_json(r#"{
  "version": "3.0",
  "extensions": ["https://mapseekai.github.io/raster-style/extensions/raster/tile/v1.0.0/schema.json"],
  "renderer": {"type": "pseudocolor", "bidx": [1], "colormap_name": "viridis"},
  "stretch": {"method": "linear", "rescale": [[0, 3000]]},
  "raster:tile": {"format": "png", "tilesize": 256}
}"#)?;

也可以使用 TileStyle::from_raster_query 解析原始 Q3 查询字符串,或用 TileStyle::from_raster_style(&RasterStyle) 接收 SDK 已校验对象。 RasterStyle 从 async_geotiff::style 导出。 style.raster_style_json() 返回规范化 JSON。修改样式时重新解析输入;直接覆盖 TileStyle 不暴露可变字段;format() / tilesize() 提供只读输出配置。

Tile 与 Mosaic 是独立版本扩展:在 extensions 声明精确的 Schema URL, 配置位于 raster:tile、raster:mosaic。Q3 使用 extensions 传输 URL 数组、 extension_fields 传输业务字段对象,均为百分号编码的 JSON。 推荐用 raster_style::encode_query 编码已校验的 SDK 文档。 校验不完整或声明第三方扩展的样式在执行前即被拒绝。

HTTP Q3 输入

单波段色带:

/tiles/WebMercatorQuad/0/0/0.png?version=3.0&type=pseudocolor&bidx=1&method=linear&rescale=0,3000&colormap_name=viridis

RGB 支持将一组范围广播到三个输出:

version=3.0&type=rgb&bidx=1&bidx=2&bidx=3&method=linear&rescale=0,3000

dataset、mode、_v 是示例服务上下文,不属于样式文档;TMS 和瓦片坐标仍在路径中。 服务保留原始查询片段,由 SDK 解码一次。+ 必须写成 %2B,空格写成 %20, 不要先 URL 解码再调用 from_raster_query。JSON 入口是 Rust API;示例 HTTP 服务使用 Q3 GET。 PNG 是默认编码。WebP 要启用 webp feature,声明 Tile 1.0.0 扩展,并配置 raster:tile: {format: "webp", lossless: true}, 并使用 .webp 路径;路径与样式格式必须一致。

拉伸与颜色

  • 支持 gray、rgb、pseudocolor、categorized、single_color。
  • method=none(含省略)对显示路径固定使用 [0,255],不会自动读取统计值。
  • method=linear 必须给出 rescale;RGB 接受一组广播范围或三组逐通道范围。
  • 显示路径支持 range_policy=clamp|transparent;透明策略在颜色处理前判断越界。
  • 命名色带使用项目固定依赖中的 colorous 256 项表:viridis、magma、inferno、plasma、cividis、turbo、greys。
  • 原生 colormap 精确值对象按数据值匹配;区间数组使用半开区间 [lo,hi),末区间也不包含上界。 pseudocolor 在显式拉伸或 Gamma 后转为 0–255 色表索引;categorized 始终按数据值精确匹配。
  • gray 支持 renderer_invert;single_color 的有效输入包括 0 和负数。
  • opacity 作用于输出 Alpha;最终 Alpha 为 0 时输出透明黑色。

categorized 只支持显式精确值表与 nearest,读取原始层,避免未经验证的概览改变类别。 普通数值样式支持现有 nearest、bilinear、cubic、cubic_spline、lanczos、average 核。 每个依赖波段分别重采样并传播有效性;源 Alpha 波段暂不支持,会在读取像元前报错。

cubic_spline 在整数像素中心仍会平滑数据。因此,请求瓦片网格与源网格精确对齐时 也会执行该核,直接瓦片渲染与 warp 路径保持相同重采样语义。Cubic、CubicSpline 和 Lanczos 对接近数值上限的有限 F64 常量也保持有效,不会因中间计算溢出而变透明。 实际非有限样本或无法表示的结果仍然无效。

统计拉伸与曲线

支持全部 7 种方法:none、linear、minmax、percentile、stddev、 histogram_equalization、curve。三个示例页均提供对应参数:

method=percentile&percentiles=2,98
method=stddev&stddev=2
method=histogram_equalization
method=curve&curves=[[[0,0],[128,0.5],[255,1]]]

百分位对排序样本做线性插值;标准差为总体标准差;直方图均衡使用经验 CDF,不使用分桶近似。 曲线点为 [数据值,归一化输出],支持一条广播曲线或三条 RGB 曲线。实际 Q3 URL 中需编码 JSON。

Tiler 与 MosaicTiler 在完整数据源足迹或固定 mosaic 源集合的联合足迹上,绑定 1024 × 1024、EPSG:4326 的共享统计网格。网格北向上,经纬度像元中心等距,覆盖及有效性 mask 从源继承;overview 根据各源完整范围和固定网格尺寸选择,与输出瓦片缩放级别无关。 统计网格重放相同的重采样、NoData、表达式、完整元组有效性与 mosaic 阶段。 不会改成当前瓦片统计,也不直接信任嵌入式 GDAL 汇总值。

省略 statistics 时使用 dataset/mosaic 范围、sample 精度、最多 1,000,000 个行优先等距网格位置。 statistics={"scope":"dataset","accuracy":"exact"} 遍历该绑定网格所有像元, 不表示遍历源数据原生分辨率的全部像元。无效采样丢弃且不补采;空统计输出透明;常量范围映射到 0.5。

统计结果跨瓦片共享,缓存绑定 reader 实例、顺序及完整规范化样式。统计计算、源读取和 median 保留输入 受现有 CPU/内存预算约束;选定 overview 的完整读取超过预算时明确报错。最多缓存两个统计计划。

quadkey_zoom=0 的 MosaicJSON 提供固定完整源集合。分区 MosaicJSON 的统计拉伸暂报错, 避免摊平索引后丢失覆盖范围和分区绘制顺序;瓦片始终使用索引选中的源。 自定义 MosaicSource 的 statistics_assets() 必须提供与瓦片选择语义一致的完整合成集合。 未绑定集合的动态 STAC、viewport 和外部 statistics.ref 暂报错。 低层 render(ImageData, ...) 不能自行推断完整数据范围;统计类方法通过 tiler 绑定后执行。

表达式

支持十进制数、括号、一元负号和四则运算,波段编号从 1 开始。RGB 可用 ; 分隔三个输出。

version=3.0&type=gray&expression=(b5-b4)%2F(b5%2Bb4)&method=linear&rescale=-1,1

该 NDVI 示例要求第 5 波段是近红外、第 4 波段是红光,使用前检查数据元信息。 表达式与 bidx 互斥,可与受支持的 Gamma 组合。无效源值、除零或非有限结果透明。 当前不支持函数、条件运算和科学计数法;SDK 与现有表达式解析器共同限制输入大小。

颜色公式

effects.color_formula 支持 Gamma,按数组顺序执行;Q3 示例:

version=3.0&type=gray&bidx=1&color_formula=gamma%20rgb%202

暂不支持外部统计快照、calibration(除 none)、index、color_mapping、源调色板、 mode 重采样、地形、第三方扩展、其他颜色操作、JPEG 与有损 WebP。请求这些能力会报错。

Mosaic

启用默认的 mosaic feature 后,JSON 中声明:

"raster:mosaic": {"pixel_selection": "highest", "stage": "after_channels", "rank_channel": 1}

在 extensions 声明官方 Mosaic 1.0.0 Schema URL。Q3 的 extensions 参数传输声明数组,extension_fields 传输包含 raster:mosaic 的对象;旧的镶嵌短参数不再接受。 支持 first、highest、lowest、mean、median,以及 before_channels / after_channels 两个阶段。 使用 mosaic.tile(coord, &style).await?,选择方法直接取自样式。 tile_with_options(coord, &style, &options) 提供请求取消和超时控制。

before_channels 的排序位置对应去重后按源波段号升序排列的依赖表;after_channels 对应输出通道顺序。rank_channel 从 1 开始,仅用于 highest/lowest。 所有分量有效的同源元组才参加合并;不会把不同源的通道拼成一组。Gamma、色表和 opacity 在合并后执行一次。源 Alpha 波段限制仍适用。

资产列表由 MosaicJSON、STAC 或自定义 MosaicSource 提供,保持在样式之外。 配置、资源限制与示例见镶嵌指南。

迁移

旧 from_query / from_pairs、ValidatedTileStyle、compile_validated、可变样式字段、 Stretch / ColourDefinition / Colour / lut_from_stops 与独立 mosaic selection 参数已移除。 统一使用 from_json / from_raster_query / from_raster_style。 TileStyle::default() 是显式灰度波段 1、固定 0–255 的新规范样式。 HTTP 请求必须包含 version=3.0&type=...,旧参数与未知字段返回错误。 三个查看器只生成 Q3,Opacity 由服务端应用一次;MapLibre 提供 mosaic 阶段和排序通道。

旧输入新输入
bidx=1&colormap_name=viridis&rescale=0,3000增加 version=3.0&type=pseudocolor&method=linear
RGB 的三组相同 rescale一组 rescale 即可广播,但需显式 type=rgb 和三个 bidx
不指定拉伸,对非 U8 自动 stddev新格式使用固定 [0,255];需调用方显式给定范围
连续 stops 数组 colormap不能直接复用;新格式原生数组是区间表,连续 color_mapping 尚未实现
stretch=percent&pc=2,98method=percentile&percentiles=2,98

2 - 镶嵌与 STAC

从 MosaicJSON、STAC 或自定义数据源渲染重叠 COG 资产。

默认启用的 mosaic Cargo feature 提供 MosaicTiler 和 MosaicSource trait; 不需要镶嵌的应用可以关闭默认 features。由于这也会关闭 proj,仍需通用 CRS 转换时 请使用 --no-default-features --features proj。数据源将瓦片坐标映射为资产列表; tiler 打开并重投影这些资产,归并重叠像元,然后统一渲染合成结果。

MosaicJSON

运行内嵌示例,或传入一个 MosaicJSON 文件:

cargo run --example mosaic_json
cargo run --example mosaic_json -- /path/to/mosaic.json

解析器支持 MosaicJSON 0.0.3。其 quadkey 索引定义在 WebMercatorQuad 中; 将 MosaicJSON 数据源用于 WorldCRS84Quad 会返回查询错误。

在进程启动时把示例服务连接到文件:

ASYNC_GEOTIFF_MOSAIC=/path/to/mosaic.json \
  cargo run --release --example serve

镶嵌瓦片随后可通过 /mosaic/tiles/... 获取。

Raster Style 3.0

let style = TileStyle::from_json(r#"{
  "version": "3.0",
  "extensions": ["https://mapseekai.github.io/raster-style/extensions/raster/mosaic/v1.0.0/schema.json"],
  "renderer": {"type": "rgb", "bidx": [3, 2, 1]},
  "stretch": {"method": "linear", "rescale": [[0, 3000]]},
  "raster:mosaic": {"pixel_selection": "highest", "stage": "before_channels", "rank_channel": 1}
}"#)?;
let tile = mosaic.tile(coord, &style).await?;

before_channels 先合并输入依赖,再执行表达式;after_channels 先逐源计算表达式, 再合并输出。上例的依赖表是 [1,2,3],因此 rank_channel=1 比较源波段 1; 改为 after_channels 后比较第一个输出,即源波段 3。并列保留源顺序靠前的完整元组。 mean/median 只对同一组完整有效元组逐通道求值,避免极值相加溢出。

Q3 请求示例:

/mosaic/tiles/WebMercatorQuad/0/0/0.png?version=3.0&type=rgb&bidx=3&bidx=2&bidx=1&method=linear&rescale=0,3000&extensions=%5B%22https%3A%2F%2Fmapseekai.github.io%2Fraster-style%2Fextensions%2Fraster%2Fmosaic%2Fv1.0.0%2Fschema.json%22%5D&extension_fields=%7B%22raster%3Amosaic%22%3A%7B%22pixel_selection%22%3A%22mean%22%2C%22stage%22%3A%22after_channels%22%7D%7D

MapLibre 的 Source 选择 mosaic 后可以配置阶段和排序通道。资产地址仍由服务端固定, JSON/Q3 不携带资产列表。新格式要求显式 mosaic 配置;源 Alpha 波段暂不支持,返回能力错误。 完整支持范围见样式指南。

像元选择

策略行为
First第一个有效像元获胜;瓦片被完全覆盖后可提前停止。
Highest按 rank_channel 选择最大值所在的完整元组。
Lowest按 rank_channel 选择最小值所在的完整元组。
Mean对有效样本流式求均值,内存不随资产数量增长。
Median对有效样本求中位数,完成前需要保留所有参与图像。

bidx 和 rank_channel 都从 1 开始;后者是合并阶段的通道位置。

MosaicConfig 默认每批并发处理 8 个资产,每个 MosaicTiler 的 reader 池最多保留 256 个已打开 reader,并把每张请求瓦片的资产数硬限制为 64。超过上限时返回错误, 不会截断资产后返回部分结果。三个限制都通过 builder 配置:

use std::sync::Arc;

use async_geotiff::io::block_cache::BlockCache;
use async_geotiff::io::cache::CacheConfig;
use async_geotiff::mosaic::{HttpAccessPolicy, MosaicConfig, MosaicTiler};

let cache = Arc::new(BlockCache::new(CacheConfig::default()));
let config = MosaicConfig {
    chunk_size: 4,
    reader_capacity: 64,
    max_assets_per_tile: 32,
    ..Default::default()
};
let mosaic = MosaicTiler::builder(source)
    .config(config)
    .block_cache(Arc::clone(&cache))
    .http_policy(HttpAccessPolicy::strict())
    .build();

对于不可信或低缩放级别的索引,应保留资产上限以避免请求放大。数据源应提供确定性的资产顺序, 因为 first 和极值并列时依赖该顺序。Median 保留输入上限为 256 MiB,另受共享工作内存预算约束。

STAC 示例

启用 stac 并提供全部三个启动配置:

ASYNC_GEOTIFF_STAC_URL=https://earth-search.aws.element84.com/v1 \
ASYNC_GEOTIFF_STAC_COLLECTION=sentinel-2-l2a \
ASYNC_GEOTIFF_STAC_ASSET_KEY=visual \
  cargo run --release --example serve --features stac

API、集合与资产 key 在进程启动时固定。HTTP 查询参数无法把示例变成任意 STAC 或 COG 代理。

启动后打开 http://127.0.0.1:8080/maplibre。配置 STAC 时,MapLibre 查看器默认 选择 mosaic 模式,无需猜测瓦片坐标即可验证目标集合。

自定义认证、代理或超时时,在调用 build() 前把配置好的 reqwest 0.11 ClientBuilder 传给 StacSource::with_http_client_builder。数据源保留这些配置, 并强制最多十次同源重定向;跨源跳转在发送凭据前被拒绝,传输错误不包含完整 URL。 已弃用的 with_http_client 现在会在 I/O 前报错,因为已构建客户端的重定向策略无法 覆盖。StacSource::new 的签名保持不变。

HTTP 资产策略

默认策略允许公网和私网 HTTP(S) 资产,但阻止 loopback、link-local 和云元数据地址。 对于完全不可信的文档,请使用 HttpAccessPolicy::strict():它要求 HTTPS,并额外阻止 私有地址范围。permissive() 只应服务于运维方完全控制的资产列表。

示例服务显式允许自身的 HTTP 主机名,供配置的镶嵌读取 /data 资产;其他主机使用 默认策略,不提供环境变量覆盖。接受不可信 mosaic 或 STAC 文档的服务应 自行构造 MosaicTiler,并像上例一样通过 builder 传入 strict()。

镶嵌错误和日志会隐藏预签名 URL 的查询字符串。 访问策略是 URL 解析防护,不是完整的出站代理沙箱。应用仍需负责客户端超时、重定向 策略、出站防火墙、文档大小限制,以及自己在库外增加的日志。

3 - 生产运行

配置缓存、限制 CPU、保护远程资产并导出可观测性数据。

共享一个缓存

解码块缓存的默认预算是 512 MiB。拥有多个 reader 的服务应把同一个 Arc<BlockCache> 注入全部 reader 和 mosaic,并为每个不同 COG 使用稳定的源 ID, 避免缓存键冲突。

这个预算只覆盖缓存中常驻的解码块,不等于进程总 RSS。飞行中的压缩字节、解码和 重投影缓冲区、编码响应、reader 元数据与 mosaic reducer 状态会额外占用内存;其中 Median 会保留全部参与图像直到归并完成。

默认瓦片入口共享最多准入 64 个请求的 RequestLimiter,以及独立于解码缓存、 用于活跃工作的 512 MiB WorkBudget,也可以注入自定义实例。这些计账上限不等于 严格 RSS 上限;仍需限制单瓦片资产扇出和调用方保留的输出,并用有代表性的负载确定 容器内存。默认值、内存竞争下的有界重试、取消和源快照说明见 运行限制与源一致性。

通过 BlockCache::stats() 可观察:

  • hits 与 misses
  • decoded 与 fetched
  • entries
  • resident_bytes

可进一步计算命中率、fetch/decode 放大比,以及常驻字节占配置预算的比例。

限制 CPU 工作

解码、拼接、重投影、镶嵌归并、渲染与编码都是 CPU 密集型工作。它们通过受 CpuLimiter 限制的 spawn_blocking 运行。非 mosaic CogReader 与 Tiler 接受 调用方提供的 limiter;MosaicTiler 在资产与最终渲染之间共享一个内部 limiter, 但不能接入非 mosaic limiter。默认值取主机可用并行度,并把 0 修正为至少一个 permit。

Tiler::new 会复用其 reader 携带的 limiter:

use std::sync::Arc;

use async_geotiff::CpuLimiter;
use async_geotiff::io::cog::CogReader;
use async_geotiff::tiler::Tiler;

let cpu = CpuLimiter::new(8);
let reader = Arc::new(
    CogReader::builder()
        .source_id("scene-a")
        .cpu_limiter(cpu.clone())
        .open_http("https://example.com/a.tif")
        .await?,
);
let tiler = Tiler::new(reader);

示例服务的 CPU 计数方式取决于数据路径。命令行默认 COG 使用相互独立的 reader 解码 与 tiler 渲染 limiter,两阶段可以重叠;延迟选择的本地数据集复用一个 AppState limiter,其大小取两项配置中的较大值;MosaicTiler 还拥有自己的共享 limiter。因此 两个环境变量是组件调优项,不是通用的进程级 CPU 上限。需要单一上限时,应在库级别把 同一个 CpuLimiter 注入所有支持注入的非 mosaic reader 与 tiler。

当前 MosaicTiler 拥有内部共享 limiter,但 builder 不支持注入非 mosaic 路径的 limiter。因此,目前不支持对混合 mosaic 与单 COG 流量设置严格的数值型 CPU-job 上限。库外请求并发限制只能提供粗粒度背压,并不等同于共享 permit 预算。

不要在没有测量时主动降低瓦片并发。过小的限制会给每次瓦片请求增加排队时间;应先 观察 P95 延迟与 CPU 竞争。

调整访问模式

  • 多数据集服务或大范围平移/缩放场景可增加缓存容量。
  • 读取延迟敏感时优先使用 ZSTD 压缩 COG,而不是 DEFLATE。
  • 示例服务默认预取一圈原生块;不希望产生额外对象存储 GET 时,设置 ASYNC_GEOTIFF_PREFETCH_RING=0。
  • 对不可信索引保持 MosaicConfig::max_assets_per_tile 有界。

导出 trace 与指标

Tiler::tile 和 CogReader::read_window 会发出 tracing span。需要 OTLP trace 时, 在应用中连接 tracing-opentelemetry layer;库本身有意不依赖 OpenTelemetry。

在 HTTP 或应用边界记录请求量、延迟、错误量以及 Ok(None) 比例;另行轮询缓存统计, 观察内存与远程读取行为。

保护远程访问

当 mosaic 或 STAC 文档不可信时使用严格的 HttpAccessPolicy。凭据应配置在 object_store 实例上,而不是嵌入资产标识。应用边界也应避免记录原始预签名 URL。

4 - 运行限制与源一致性

工作内存、请求准入、取消和固定对象快照的契约。

工作内存与缓存

默认 reader、tiler 和 mosaic pool 共享 WorkBudget::global() 的 512 MiB 活跃工作预算。WorkBudget::new(bytes) 创建独立预算;通过 ReaderConfig::work_budget、Tiler::with_work_budget 和 MosaicTiler::builder(...).work_budget(...) 注入同一个实例,才能共享应用上限。 used_bytes()、peak_bytes() 和 limit_bytes() 提供计账数据。

低层预留失败立即返回 AgError::ResourceLimit。公开 tile、warp、mosaic 请求会先 退出失败的一轮,再等待独占准入,最多重试一次;等待和重试都计入原 deadline。 单个请求本身超预算时仍失败。直接调用 CogReader 不提供这种请求级重试。 阻塞任务和受管理的响应缓冲区会保留预留,直到最后一个持有者释放。

这不是操作系统 RSS 上限。解码缓存、调用方持有的完成图像、分配器、TLS 和应用自身 分配另有生命周期。通过 CacheConfig::max_bytes 限制缓存,并限制输出保留数量。

Reader 设置默认值
源窗口像素16 × 1024 × 1024
窗口字节/压缩抓取批次256 MiB
每窗口块数4096
单块声明的解码字节64 MiB
打开时累计元数据8 MiB
IFD 数量256
每 IFD 条目4096
并发前台窗口8

使用 ReaderConfig::default() 并明确覆盖字段。超限、算术溢出和非法元数据在相应 抓取/分配前失败。后台预取即时尝试获取预算,前台占用时跳过。内置解码器检查 未压缩、Deflate/OldDeflate、LZW、ZSTD 和 JPEG 输出形状;调用方自行提供的解码器 仍由调用方负责。

请求准入与取消

默认共享 RequestLimiter 准入 64 个瓦片请求,超出立即返回 AgError::Overloaded。 使用 Tiler::with_request_limiter 或 MosaicTilerBuilder::request_limiter 共享自定义实例;mosaic 内部资产任务不会再次占用请求名额。

默认 timeout 为 30 秒,包含 I/O 和 permit 等待。TilerConfig、MosaicConfig 提供 max_in_flight_requests 与 request_timeout,构造时可使用 ..Default::default()。tile_with_options 和单源 warp_tile_with_options 接受含单次 timeout、RequestCancellation 的 RequestOptions。 cancel() 返回 AgError::Cancelled;超时返回 AgError::DeadlineExceeded。

取消会停止后续阶段并丢弃待完成的 I/O,但不会抢占已执行的 CPU 指令,也不会强制 终止远端处理。仍在运行的阻塞任务保留准入和内存计账,直至结束。直接打开 reader 发生在 tile 请求之外,需要包含打开时间时,应由应用增加外层 timeout。

示例服务将 ASYNC_GEOTIFF_MAX_IN_FLIGHT_REQUESTS 与 ASYNC_GEOTIFF_REQUEST_TIMEOUT_MS 传到默认 COG、本地懒加载、MosaicJSON 和 STAC 入口,HTTP deadline 包含数据集查找/打开;增大设置后不会残留固定的 64 请求或 30 秒总 deadline。传输层连接/读取 timeout 独立。单 COG 支持 ASYNC_GEOTIFF_PREFETCH_RING,mosaic reader 默认不预取。

HTTP mosaic 错误标签移除 URL userinfo、query 和 fragment;对象存储 key 保持原语义。

Mosaic 顺序与波段

MosaicJSON 去重保留资产列表中的首次出现顺序。前缀查找按 quadkey 字典序遍历, 保留各列表顺序。样式的 raster:mosaic 设置 pixel_selection、stage 和从 1 开始的 rank_channel。before_channels 使用按波段号排序并去重的源依赖; after_channels 使用计算后的输出通道。整个 tuple 有效才能参与,Highest/Lowest 保留获胜资产的完整 tuple,同值时按资产顺序决定。

源依赖分别 warp,避免无关波段的 nodata 影响插值。Gamma、色带和透明度在归并后 执行一次。仅支持 calibration none;旧 unscale 参数已移除。warp_tile 返回紧凑依赖或计算通道,不再返回全部源波段。

固定对象快照

受管理的 open_http 和 open_object_store 默认使用 SnapshotPolicy::RequireValidator,需要 strong ETag 或不可变对象版本。 条件读取和缓存身份将元数据与像素固定到同一快照;源发生变化时返回错误,避免 混合版本。支持版本的存储可继续提供固定的旧版本,本地受管理打开也提供 validator。

不透明 ObjectReader 无法提供底层条件请求,因此 .open(reader) 要求显式设置 .snapshot_policy(SnapshotPolicy::AssumeImmutable)。这由调用方保证源不可变, 不是库验证出的快照一致性。

一致性依赖真实 validator 和后端原子写入契约,无法检测复用旧 validator 的字节 变更或违反契约的原地文件写入。没有自动刷新:直接 reader 应重新打开;mosaic 可用 invalidate_source(key, source_id) 或新的源版本身份触发重开。已持有的 reader Arc 仍指向原快照;旧版本不可获取时,其未缓存读取会失败。

5 - 本地负载测量与基准

无需外部服务,复现有界延迟与峰值 RSS 测量。

这些工具从 Git 检出目录运行,支持 macOS 和 Linux;它们是开发工具,不会在应用 依赖本库时执行。先单独编译优化后的二进制,避免编译器内存混入测量:

cargo build --release --locked --example load_audit --features mosaic
python3 scripts/run_load_audit.py --samples 32 --concurrency 4

默认结果写入被 Git 忽略的 target/load-audit/results.json。可用 --output 设置其他路径,用 --concurrency 1 或 8 比较并发。采样限制为 4–128, 并发为 1–16;超过 120 秒会终止子进程。脚本只依赖 Python 标准库。

负载在临时 loopback HTTP 服务中提供 64×64 Deflate TIFF,带 32×32 overview、 三个波段、四个原生块和 nodata 角落,每个 GET 注入 2 ms 延迟。直接调用库的瓦片 API,输出 64×64 PNG;不需要凭据和公共数据,也不代表示例服务 HTTP 路由的端到端 性能。冷请求包含 reader/客户端/元数据,热请求复用 reader 和解码块;mosaic 使用三个独立 URL 的相同像素与 Mean reducer。吞吐包含批次屏障,不是开放到达率。

JSON 包含 nearest-rank P50/P95/P99、缓存计数、GET 数量、准备的响应字节、活跃 处理器、工作预算峰值,以及取消/deadline/准入拒绝/提前内存拒绝的观测。32 次 采样的 P99 是最大值,不能当成稳定的生产尾延迟。“响应字节”是服务端准备的数据, 不证明已送达取消的客户端;取消返回后仍可能有远端工作完成。

脚本记录 UTC、平台、CPU、Rust 版本、提交及工作区状态、二进制和 fixture 的 SHA256、CPU 时间及子进程的 wait4 ru_maxrss。macOS 返回字节,Linux 的 KiB 会换算为字节。RSS 是整个负载进程全程峰值,不是各场景峰值或进程树总量。

这些是单机有界合成测量,不证明生产容量、任意恶意编解码输入的内存上限或无限 请求流表现。fixture 可用 python3 tests/fixtures/generate.py 重建,Deflate 字节也受本地 zlib 版本影响。

重采样微基准

cargo bench --locked --bench resampler_bench

六组场景比较连续/跨步内存布局下带/不带 mask 的 Bilinear 采样,以及带/不带 mask 的 Average 降采样,测的是核本身成本,不是 HTTP 延迟或跨 CRS 流水线吞吐。 Criterion 只作为开发依赖,不会成为应用使用本库时的依赖。