Skip to content

Releases: Linductor-alkaid/kairo

kairo v0.7.3

Choose a tag to compare

@github-actions github-actions released this 28 Oct 19:38

[0.7.3] - 2026-10-29

0.7.3 主体内容(roadmap §5):堆分配优化阶段二(TaskResult 轻量
Future + submit_v2)、返回值语义补齐(取值 CpuGpuTask +
ResultAdapter + ExecutionReport),以及先行落地的分主体在途份额
admission(issue #222 / Mira 台账 EXE-20261028-001)。全部为
additive;submit() 等既有 API 行为与 0.7.2 逐项一致。设计见
docs/design/scheduling_runtime.md §16/§17 与
docs/design/subject_bucket_admission.md。

新增

  • TaskResult 轻量 Future 与 Executor::submit_v2(roadmap §5.0,
    堆分配优化阶段二)
    :<kairo/task_result.hpp> 单次分配的
    promise/future 一体单元——结算仲裁(settled CAS)与值发布(ready
    release/acquire)分离,get() 快速路径无锁读值(实测命中率 99.7%);
    submit_v2 与 submit 语义逐项同构(admission / 空任务拒绝 /
    queued soft timeout / 异常与超时观测 / 释放时序),提交上下文与
    bind 结果本体并入同一控制块。实测 submit 主路径 4.00
    allocs/task / 488 bytes
    (v0.7.2 submit 为 7.00 / 512;旧路径
    不变)。broken promise 契约与 std::promise 析构对齐:
    shutdown(false) 丢弃排队任务时 get() 以
    future_error(broken_promise) 就绪,不挂死。可观测:
    AllocationMetrics 追加 fast_path_get_count /
    slow_path_get_count("快速路径命中率" = fast/(fast+slow))。迁移
    策略:opt-in 新 API,submit() 不受影响(0.8.0 前不弃用)。

  • 取值 CpuGpuTask + ResultAdapter + ExecutionReport(roadmap §5.1):
    CpuGpuTask<CpuFunction, GpuFunction, R = void>(末尾默认模板参,
    两参拼写与 void 语义逐位不变)+ cpu_gpu_task<R>(cpu, gpu) 工厂 +
    CpuGpuTask::result_adapter()。R 非 void 选中 GPU 时必须显式提供
    ResultAdapter<R>::gpu_extract(GPU worker、GPU callable 返回后
    调用;async 配置 = launch 完成点,设备搬运与同步责任在用户侧),
    否则按 fallback 提交前结构化拒绝或 AllowCpu 回退——宁拒不静默降级
    void。submit_auto(CpuGpuTask) 泛化为条件返回:void 实例化逐位
    不变;非 void 产出 ExecutionReport<R>{result, decision}(报告
    实际选择路径;回退时 decision 记录回退后最终路径;拒绝时 result
    以 runtime_error 就绪、报告即终态)。GPU 结算双保险:kernel 包装
    主结算(成功值/异常保真)+ stream 完成计时 sink "恰一条交付"兜底
    (校验失败/launch 失败/post-kernel 设备错误/停止排空全路径)。需要
    不支持完成计时的 GPU 执行器承接取值任务会被提交前拒绝。

  • 分主体在途份额运行期接口:Executor::set_subject_max_in_flight_tasks(subject, max)
    (max == 0 解除该主体约束)、get_subject_max_in_flight_tasks()、
    get_subject_in_flight_submissions()、get_subject_quota_status()
    (SubjectQuotaStatus 快照,按 key 排序)。每个已配置主体独立计数在途
    提交并以份额约束,与全局 max_in_flight_tasks 同时生效;仅运行期接口,
    ExecutorConfig 无初始映射。

  • 分桶键进入提交 API:TaskOptions::subject(空 = 不分桶)+
    TaskBuilder::subject()。一期带键路径 = submit_auto(TaskBuilder) 与
    submit_after*(TaskBuilder);其余提交路径仅全局约束(见 API.md §3.12
    覆盖路径说明)。

  • 拒绝可区分性(共用 §3.11 拒绝面,不新造异常/failure kind):
    ExecutorFailureStatus 追加 subject_quota_exhausted_count(分桶拒绝时
    与 capacity_exhausted_count 同时递增,前者是后者子集);
    ExecutorFailureEvent 追加 subject 字段(分桶拒绝携带键,空 = 总量
    拒绝)。分桶拒绝消息 Subject in-flight quota exhausted (key=…)。

  • 测试:tests/test_subject_bucket_admission.cpp(standalone)锁定
    份额互不影响、分桶/总量拒绝可区分、终态恰好一次释放、热更新/解除、
    shutdown 与零回归锚;tests/test_subject_quota_concurrency.cpp
    (standalone,参与 TSAN job)锁定并发契约——热更新严格可见性与并发
    交错弱一致、解除/重建代际隔离、stress 下无泄漏/无越权/恰好一次释放;
    tests/test_api_doc_admission_fields.cpp 扩展锁定新字段与 API.md
    §3.12。

  • 并发契约文档化(PR #223 审查):热更新弱一致语义(接纳快照点 =
    注册表查表临界区;set 完成后的新提交必用新份额,交错中的已开始接纳
    允许按旧快照完成)与代际语义(活键原位缩放同代;set(key,0) 解除即刻
    生效、已接纳落账孤儿计数;同名重建新代从 0 起计不继承残量;查询面只
    反映当代)。见 docs/design/subject_bucket_admission.md D-2/D-5。

  • 裸形态带键入口(修订 R-1,下游反馈):submit_auto(kairo::subject("key"), fn)
    ——裸 callable 写法经 SubjectKey 标签进入分桶接纳点,与带键
    TaskBuilder 形态语义逐位一致;SubjectKey 构造 explicit(字面量误用
    编译失败而非静默错绑)。SubjectQuotaStatus 追加 admitted_total
    (当前代累计接纳数):份额已配置但该值停在 0 = 键未生效。

  • 键脱敏约定与低报警示(修订 R-2/R-3,下游反馈):分桶键逐字复制进
    异常消息/failure 事件/状态快照,必须使用不可识别的派生标识,键集清理
    责任在调用方(API.md §3.12);解除后同名重建的短暂窗口内
    get_subject_in_flight_submissions() 低报真实在途(差额上界 = 解除前
    份额),已提升为显式调用方注意事项,监控口径 = 超额上界 + 自愈时间。
    设计记录见 docs/design/subject_bucket_admission.md 修订节。

修复

  • submit_priority_scheduled 异常终态的数据竞争(发布前混合负载
    soak 的 TSAN 短 soak 实证,45 份同根因报告):任务包装在
    promise.set_exception 发布之后仍经 is_deadline_drop_exception
    (rethrow 语义)访问异常对象本体,与消费者线程的 catch/析构并发
    ——分类移到结算前,DropIfLate 归类与 failure 观测语义逐项不变。
    修复后 TSAN soak 零报告(129k 次异常路径同等覆盖)、退出码 0。

稳定性验证(发布门禁)

  • 40.2 分钟自适应调度(AdaptiveScheduler 注入)混合负载 soak:
    12 通道(submit/submit_v2/submit_auto(TaskBuilder)/cpu_gpu 回退/
    SubjectKey/tracked/delayed/cancellable+取消竞态/batch/周期+重排),
    54,337,566 提交 == 结算(零丢失),均值 22,546 tasks/s;
    RSS 平稳(479 样本回归斜率 1.37 MiB/h,无趋势);观测面单调性
    零违规;closure_graveyard_size()==0;池命中率 1.0;TaskResult
    快/慢 get 7,832,436/0。24h 级持续 soak 留作 0.7 系列回归项。

kairo v0.7.2

Choose a tag to compare

@github-actions github-actions released this 19 Oct 15:10
3841089

[0.7.2] - 2026-10-19

优先级语义转移到调度器(roadmap §4.0,0.7.x 唯一破坏性变更)+
堆分配优化阶段一(§4.1)+ 反馈覆盖扩展(§4.2)+ 生命周期可靠性
收尾(§4.3)。设计记录见 docs/design/scheduling_runtime.md
§14/§15 与 docs/design/priority_refactoring_decision.md。

变更(Breaking,仅此一项)

  • Executor::submit_priority 已移除(0.7.2-rc1 曾标记
    [[deprecated]]):优先级是调度策略维度而非提交协议,统一经
    submit_auto(kairo::TaskBuilder(fn).priority(p)) 表达——与
    QoS/deadline 共享同一 IScheduler 协议(effective_priority_for()
    咨询、显式 priority 永不被覆盖)。调度顺序(priority → EDF → FIFO)
    与 0.7.1 逐位一致:共享内部实现
    submit_priority_scheduled 保留(供 facade 复用,非公共协议),
    admission 与 task_id(facade_submit_priority)不变。
  • submit_batch_priority 行为不变、内部改走共享实现:不再经由
    submit_priority(已移除),无弃用警告路径。
  • 内部层 ThreadPool::submit_priority / try_submit_priority* 不变。

新增

  • 迁移脚本 scripts/migrate_submit_priority.sh:自动改写
    submit_priority(P, callable) 两参模式(整数字面量映射
    TaskPriority 枚举,变量经 static_cast);带额外绑定参数的调用
    保留原样并逐条报告。--dry-run 预览。
  • 堆分配优化阶段一(roadmap §4.1):submit 主路径
    9 → 7 allocs/task(-22%)、768 → 512 bytes/task(-33%)。
    ① Task 调度节点对象池(PriorityScheduler 内定容 256 Vyukov MPMC
    空闲表,单元序号防 ABA,析构-重建严格重置协议;命中率实测串行
    100%、并发 99.1%~100%,池满/池空自动回退堆分配,语义零变化);
    ② facade 提交路径单控制块整合(submit 与
    submit_priority/submit_auto(TaskBuilder) 共享路径的 promise/ready、
    提交上下文、admission 释放链、资源租约、move-only bind 结果并入
    单次分配;包装层捕获从多字段降为单 shared_ptr/裸指针,包装层分配
    5 → 2 次)。自动生效、用户无感知、无行为变化。独立验证:hotpath
    吞吐 10 轮交错 p=1 +22.6%、p=2..16 容差内,TSAN 15/15 与 ASAN 6/6
    零报告。实施记录与草案偏差清单见
    docs/design/allocation_optimization_proposal.md §9。
  • 可观测性 API:AllocationMetrics(types.hpp,Task 节点池命中/
    未命中累计);Executor::get_allocation_metrics() 与
    Executor::get_task_pool_hit_rate()(默认池快照,未初始化返回零);
    IAsyncExecutor::get_allocation_metrics() 虚方法(additive,默认零)。
  • 反馈覆盖扩展(roadmap §4.2):measurement contract 扩展到
    GPU / lockfree / realtime。① 聚合级执行反馈:AggregateExecutionStats
    (executed/over_budget/period 累计计数)+
    IRealtimeExecutor::get_aggregate_execution_stats()(默认零)+
    Executor::get_aggregate_execution_stats(name) /
    get_all_aggregate_execution_stats();realtime 执行线程内仅
    relaxed 原子计数(无逐任务回调、RT 无分配约束不破坏),lockfree
    超预算计数经 opt-in LockFreeTaskExecutor::set_execution_budget_ns()
    (默认 0 = 关闭计时)。② GPU stream 完成回调计时:IGpuExecutor
    新增 supports_completion_timing() / submit_kernel_with_timing()
    与 gpu::GpuKernelTimingRecord(每提交恰一条,completion_ns==0
    语义为"未知");CudaExecutor async kernel 经 cudaLaunchHostFunc
    探针观测完成点,回调内不做任何 CUDA 调用、计时数据转交执行器线程
    后才调用 sink(CR-153 结构性履行);submit_gpu 新增带 sink
    overload,submit_auto(CpuGpuTask) 在 wants_feedback() 且执行器
    支持时自动走计时路径(execution_duration 观测至 stream 完成点,
    queue_wait 含执行器内部队列等待),不支持时回落既有 host 侧包装。
    独立验证:新测试 19/19,全量回归 178/182(4 失败为预存 flaky,
    A/B 定性),TSAN 零告警。实施记录见
    docs/design/scheduling_runtime.md §15。

修复(roadmap §4.3 生命周期可靠性收尾)

  • CR-054:实时线程内置循环的 stop 改为可中断等待(cv 绝对等待 +
    stop 通知),stop 延迟不再随周期线性增长;自停止请求后不再发起新
    一轮用户周期回调。
  • CR-055:BlockingIO 的用户 wakeup() 移出生命周期锁(重入不自
    死锁);并发 stop 新增终结栅栏,不再提前返回观测到未终结状态。
  • CR-057:SerialExecutionContext 新增 reserve_guarded() RAII 预留
    句柄——未 publish 析构自动 abandon,预留永不 publish 不再能卡死整
    个上下文的 FIFO 水位;修复 worker 线程内自析构的 terminate 隐患与
    shutdown join 判定的数据竞争。
  • CR-105:WorkerHandle 经生命周期令牌作失效检测,facade 析构后
    操作退化为无操作而非悬垂解引用。
  • CR-113 / CR-114:ThreadPool::resize 事务化(线程创建失败整体
    回滚,不再留下队列数 ≠ worker 数的半更新状态);worker 线程内缩容
    显式拒绝(防自 join)。
  • NN-09:DropPolicy::KeepLatest 饱和语义修正为滚动窗口——
    只逐出最旧一条(计一次 overwrite),保留最新 capacity 条含新值;
    此前会丢弃整个队列内容。"坍缩为最新 1 条"的 mailbox 语义由
    LatestMailbox 承担(行为变更,钉死旧行为的测试已同步更新)。
  • CR-154:GPU stop 语义显式化——gpu::GpuStopMode{Drain, Cancel}
    • IGpuExecutor::stop(mode);CUDA/OpenCL 的无参 stop() 保持各自
      0.7.1 默认(排空 / 取消)。
  • CR-023:worker 队列 push 的字段拷贝抛出时归还 Task 内存(不再
    泄漏)。
  • CR-136:TimerOperationResult 新增 InternalError(additive)——
    定时器 request_cancel/reschedule 的内部异常不再伪装成 NotFound。
  • CR-115 / CR-043/129 / CR-116/123/125/126/134:契约文档化——
    shutdown join 无超时明示(@warning);Topic::publish 异常契约;
    其余 P2 项定性注释落源码,结果回写评审文档。

文档

  • docs/MIGRATION.md 新增 0.7.2 节(语义等价性说明、迁移模式表、
    排查清单);docs/API.md §3.2 改写为弃用注记 + TaskBuilder 示例;
    website priority 教程(中英)全面改写,choosing-submit-api /
    what-is-kairo / decisions / concurrency-antipatterns 同步新表达;
    版本与迁移页(中英)新增 0.7.2 开发快照。示例(basic_submit、
    tutorial/02_priority)与 facade 层测试调用(8 处)全部迁移。
  • CI(NN-03):realtime-allocation-guard job 扩为 guard-ON 全量
    构建 + realtime/lockfree/object_pool 套件(此前仅 guard 自身测试)。

kairo v0.7.1

Choose a tag to compare

@github-actions github-actions released this 14 Oct 15:05

[0.7.1] - 2026-10-14

v0.7.1 全部四个阶段:submit_auto 路由智能化(roadmap §3.0.1 含
§3.0.2/§3.0.3)、deadline policy(§3.2)与资源预留 ResourceLease
(§3.1)。全部为 additive(资源预留与自动推断默认关闭);默认行为
与 0.7.0 逐项一致(tests/test_capability_cache.cpp 锁定缓存开/关
的决策一致性,tests/test_deadline_policy.cpp 锁定默认策略 =
0.6.x,tests/test_resource_lease.cpp 锁定未启用预留 = 0.7.0,
tests/test_auto_inference.cpp 锁定默认无推断/DefaultScheduler
不做执行器自动选择)。

调度

  • 能力快照 TTL 缓存(submit_auto 路由智能化 §3.0.1):submit_auto
    的 CpuOrGpu / affinity 路由与 dispatch_auto 的能力消费默认经 TTL
    缓存(100ms)读取,命中路径不再逐次锁 Manager 注册表采集。不可变
    快照经 M2 同款可移植 RCU 槽发布(scheduling::detail::SnapshotSlot
    泛化为 SnapshotSlotT<T>,既有别名不变);命中判据为 manager
    state_epoch 未变且未过 TTL——注册/启停/shutdown 主动失效,TTL 只
    兜底 pending_work / GPU 可用内存等运行期数值漂移。facade 的
    start_realtime_task / start_blocking_io_worker 此前绕过注册表
    启停后端,现于成功后调用新增的
    ExecutorManager::notify_backend_state_changed() 推进 epoch。
    命中决策带 RoutingDiagnostics::CapabilityCacheHit(1u<<7)位与
    RoutingDecision::capability_from_cache 字段;SchedulingMetrics
    新增 capability_cache_hit_count / capability_cache_miss_count
    (访问点统计,与决策记录解耦)。控制 API:
    Executor::set_capability_cache_ttl()(0 关闭)/
    capability_cache_ttl() / invalidate_capability_cache();公开的
    get_executor_capabilities() 保持实时采集语义不经缓存。
    验收(配对 A/B,验收线内置 benchmark_scheduling_paths §5):缓存
    命中移除端到端 36.6% 采集成本(1415 → 898 ns/op,Windows MSVC
    Release;线 warm ≤ 0.9 × fresh)。契约测试
    tests/test_capability_cache.cpp(14 用例):计数与来源标记、TTL
    过期/关闭/重设、TTL 内注册-启动-停止主动失效、决策一致性矩阵、
    并发 + epoch 扰动下 hit+miss 守恒。

  • deadline policy(roadmap §3.2,additive,默认 = 0.6.x):
    TaskOptions::deadline_policy(DeadlinePolicy::RunAnyway 默认 /
    DropIfLate / CancelIfLate)在开始执行时裁决——与 0.6.1
    miss-observe 同点、同"严格已过才算错过,恰好相等接受"边界,不影响
    提交时点的 DeadlineExpired 准入拒绝与 EDF 排序。

    • RunAnyway:0.6.x 行为逐位一致(错过仍执行 + DeadlineMissed
      failure 事件)。
    • DropIfLate:错过不执行用户代码,future 以
      TaskCancelled(TaskCancellationReason::DeadlineMissed) 终态就绪;
      计 deadline_missed_count + 新增 deadline_dropped_count;遵循
      取消类约定不进 failure 统计(结算分类器
      is_deadline_drop_exception 保证不落入 task-exception)。
    • CancelIfLate:错过向协作停止源发请求(非抢占),任务仍启动,
      用户代码经新增的 kairo::get_stop_token()(<kairo/stop_token.hpp>,
      inline thread_local + RAII 守卫,嵌套安全)轮询并自行退出;
      非任务上下文返回空令牌。
    • 依赖传播:tracked 提交新增 submit_after / submit_after_with_handle 的 TaskBuilder 重载(携带完整
      TaskOptions:deadline/策略/QoS/优先级,QoS→默认优先级映射与
      effective_priority_for 咨询语义与 submit_auto 一致)。上游
      DropIfLate 丢弃 → 任务图落 Failed(异常 TaskCancelled(DeadlineMissed))
      → 下游经既有 reclassify_dependency_exception 规则收到
      TaskCancelled(DependencyCancelled),零新增传播机制。
    • 边界:CpuGpuTask 本阶段忽略 policy 字段(维持 feedback 级
      miss 观测);无 deadline 时策略字段无效。契约矩阵
      tests/test_deadline_policy.cpp(14 用例:边界不漂移、三策略 ×
      强制错过、依赖传播矩阵、指标守恒)。
  • 资源预留 ResourceLease(roadmap §3.1,additive,默认关闭):
    ExecutorConfig::enable_resource_reservation + resource_quota
    (新增公开头 <kairo/resource_lease.hpp>:GPU 显存/并发槽按
    device 分桶、CPU 独占核总量的显式配额)启用后,声明了
    resources() 的 submit_auto(TaskBuilder) 与 tracked TaskBuilder
    提交在 admission 时从配额真正扣留,闭合多提交在 admission 与执行
    之间超卖同一资源的 TOCTOU 窗口;任务终态归还。

    • 授予全或无:联合需求任一维度不足整体拒绝、零部分授予;GPU 维度
      缺 device → InvalidRequirement,device 未配额 → NotConfigured。
    • 决策一致性:submit_auto 在记录决策前预留,失败改写为
      CapacityPressure + ResourceInfeasible(计入既有
      resource_rejected_count);tracked 路径以结构化拒绝结算。
    • 终态释放:detail::TerminalReleaser(CAS 恰好一次 + 析构兜底)
      经 submit_priority_scheduled / submit_tracked_with_hook 新增
      的 terminal_release 参数接入既有 admission 释放链——成功/异常/
      协作取消/丢弃/软超时/提交拒绝/shutdown 排空全部路径归还。
    • 手动入口:Executor::try_reserve(req) -> ReservationResult
      (RAII ResourceLease,move-only、release 幂等)+ 诊断快照
      get_resource_reservation_status();ResourceRequirements 新增
      gpu_concurrent_slots / cpu_exclusive_cores 维度。
    • 契约测试 tests/test_resource_lease.cpp(12 用例:opt-in 边界、
      手动授予/拒绝/RAII、GPU 各维度、任务绑定终态归还、并发超卖、
      终态释放矩阵、tracked 预留、多维全或无)。
  • 任务特征自动推断与执行器自动选择(roadmap §3.0.2/§3.0.3):

    • 自动推断(opt-in,enable_auto_inference 默认关闭;运行期
      set_auto_inference_enabled() 可调)
      :submit_auto 按任务名
      模式与同名任务完成间隔规律(有界 64 键历史表
      <kairo/task_inference.hpp>,采样经反馈通道,启用时自动附加
      测量包装)产出建议性推断——决策带 AutoInferredIntent
      (1u<<5)位 + RoutingDecision::inferred_reason + detail 建议
      (blocking → start_worker / 低延迟 → dispatch_auto /
      periodic → submit_periodic),路由不被改变(submit_auto 的
      future 契约只有默认池能履行——"建议优先于切换"的强制形态);
      显式 intent 优先并计 auto_inference_rejected_count,建议计
      auto_inferred_count。
    • 执行器自动选择(随 AdaptiveScheduler 注入 opt-in):
      IScheduler 新增 select_bounded_executor() 虚方法(默认返回
      空,DefaultScheduler 与既有自定义调度器行为不变);未指定
      preferred_executor 的 dispatch_auto(LowLatency) 由
      AdaptiveScheduler 按瞬时队列负载(pending_work/capacity_hint)
      选择 lockfree 执行器,并列取名字序,决策带 AutoExecutorSelection
      (1u<<6)位 + auto_executor_selected_count。选择只用能力
      快照(经 TTL 缓存)——lockfree 反馈通道在 v0.7.2 接入前不做
      历史负载(冷启动即安全)。
    • 契约测试 tests/test_auto_inference.cpp(11 用例:opt-in 边界、
      模式注解与路由不变、显式覆盖、运行期开关、推断表 EWMA/periodic/
      键空间上界、自动选择单元矩阵与 dispatch 集成、DefaultScheduler
      回归守卫)。

提交路径

  • submit_fast() 评审移除(§3.0.1 收敛):路线图曾规划零路由
    快速提交路径;实现后与 submit 语义重复(等价
    submit_priority(NORMAL, ...)),配对实测普通提交通道反而快
    31.4%(1881 vs 2473 ns/op,Windows MSVC Release),按 2026-10-14
    评审决定移除该 API、保留 submit。零路由语义本就由 submit
    承载(submit 系列从不产出路由决策);§3.0.1 的实际性能收益由
    能力快照缓存承载。基准 benchmark_scheduling_paths §6 改为
    submit vs submit_auto 裸 builder 守卫(submit ≤ 1.05 × bare)。

文档

  • docs/design/scheduling_runtime.md 新增 §10(能力缓存设计语义与验收、
    submit_fast 评审移除记录)与 §11(deadline policy 设计语义与验收矩阵);
    docs/API.md §3.7/§3.8、docs/MIGRATION.md 新增
    "从 0.7.0 升级到 0.7.1"(无必需迁移);版本与迁移页新增 0.7.1 开发
    快照小节(含 submit_fast 评审移除结论),中英选型页同步纯提交路径
    评审结论;docs/skill 调度卡(kairo-integration / kairo-maintainer)
    同步新 API 与诊断通道。

kairo v0.7.0

Choose a tag to compare

@github-actions github-actions released this 11 Oct 03:34
32027c2

[0.7.0] - 2026-10-10

v0.7.0 前置清债(M0,docs/design/roadmap_v0.7.md §2.1):在引入任何
自适应调度代码之前,先消除会污染反馈测量或放大自适应风险的遗留项。
全部为 additive 或纯结构改动;默认行为与 0.6.1 一致。

结构

  • executor.cpp 拆分(纯结构,零行为变化):2242 行单体实现按职责
    拆为 executor_lifecycle / executor_task_graph / executor_timers /
    executor_backends / executor_routing 五个编译单元,共享辅助提取到
    内部头 src/kairo/executor_detail.hpp。方法集合(117 个)与导出符号
    面逐一核验不变。

线程池

  • 可选防饿死 aging(CR-024,additive,默认关闭):
    PriorityScheduler::set_aging_policy(enabled, boost_interval_ns)。
    开启后 dequeue 在全部非空队列堆顶中按
    (有效优先级, EDF, 提交 FIFO)选取——堆顶任务每等待
    priority_aging_interval_ns 提升一级有效优先级(至多 CRITICAL),
    队列内部堆序与任务自身 priority 不改写。关闭时出队路径与 0.6.1
    逐位一致。ThreadPoolConfig / ExecutorConfig 新增
    enable_priority_aging(默认 false)与
    priority_aging_interval_ns(默认 100ms)。NN-05 本地队列倒置窗口
    维持文档化现状(worker 扫描顺序未变)。

可观测性

  • TaskMonitor 分片化与热路径门控(CR-071/CR-163):单把全局 mutex
    改为哈希分片(id 映射与 in-flight 快照按 task_id 分 16 片,聚合统计
    按 task_type 分 8 片),dropped/evicted/in-flight 计数改原子。
    新增热路径快速门:统计采样率为 0 时不触碰 id 映射与统计分片;
    in-flight 采样率为 0 或容量为 0 时不触碰 in-flight 分片——两门全关时
    record_task_start/complete/timeout 零取锁。配套语义补全(对齐
    set_enabled(false)):
    • set_sampling_rate(0.0) 现在清空 task_id→type 映射:已开始未结算
      的统计样本随清空丢弃(语义即"关闭统计采样");
    • set_in_flight_sampling_rate(0.0) 现在清空 in-flight 快照(此前
      已采样条目会残留至被 complete 擦除)。
      in-flight 容量语义微调:分片化后为跨分片软上界(原子计数预留,
      并发下至多短暂超限 1-2 条)。验收:采样率 0 时多线程提交吞吐与
      关闭监控持平 ±5%(配对实测 ±1.2%)。

提交路径

  • 每任务堆分配基线(CR-107,第一阶段):submit() 主路径的
    promise 与 ready 标志合并为单控制块(detail::PromiseCell);
    generate_task_id 经 std::to_chars 单次拼接;池提交路径消除
    monitor_id 中间拷贝。新增 benchmark_submit_allocations 基准
    (替换全局 operator new,确定性计数):submit 路径 10.00 →
    9.00 allocs/task(816 → 768 字节/task),tracked 路径 19.13 不变。
    剩余分配项受结构约束(move-only 可调用需间接层、双 std::function 是
    后端接口、Task 含 atomic、快照字符串是公开契约),留待接口层调整。

任务依赖

  • 依赖环检测增量化(CR-052):TaskDependencyManager 引入
    Pearce-Kelly 风格增量拓扑序(节点序号 + 反向边表)。加边快路径
    O(1)(序约束已满足),不再做锁内全图 DFS;违序时三段式受限重排,
    环检测并入同一次遍历。链式建链从 O(n²)(n=4000 约 3.9s)降至
    n=20000 约 28ms;与插入序完全相反的最坏形态仍为 O(n²) 纯内存遍历
    (与旧实现同阶,facade 真实形态全走快路径)。新增
    test_task_dependency_topo(17 用例,含 n=20000 规模回归与固定种子
    随机对拍)。

调度

  • DefaultScheduler route() 内部 pipeline 化(M1,纯结构):
    route() 重构为 约束过滤 → 候选生成 → 评分/排序 → 选择 四阶段。
    新增公开头 include/kairo/scheduling_pipeline.hpp:
    DeadlineConstraintFilter / GpuResourceConstraintFilter /
    ConstraintFilterChain<>(约束过滤,可编译期组合、首个拒绝短路)、
    IntentCandidateGenerator(0.6.1 意图路由决策树)、
    IdentityScoring(空评分实现)、select_first /
    apply_affinity_advisory(选择与 advisory)。各阶段可组合,
    后续 AdaptiveScheduler 复用过滤与候选生成、只替换评分。
    IScheduler 对外接口不变,决策结果与 0.6.1 逐项一致
    (契约测试 test_scheduling_contract_v061.cpp 一字不改通过);
    TaskRouter::route() 保留为"无过滤/无评分/无 advisory"参考路径。
    热路径实测快于 0.6.1 基线(阶段折叠为单一扁平函数,基线 36.5ns →
    35-36ns,配对 ABBA 4 轮)。

  • 反馈聚合层 FeedbackAggregator(M2,additive,默认零开销):
    新增公开头 include/kairo/feedback_aggregator.hpp。record() 在
    worker 线程无锁、无分配、noexcept 地累加执行期样本(EWMA 队列等待
    与执行时长、分桶直方图、失败率、deadline 错过),按
    (backend, executor_name, qos) 分键,per-worker 固定 32 分片(进程级
    thread_local 槽位稳定映射)。读方只读周期性合并出的不可变快照
    (RCU 风格原子 shared_ptr 指针交换发布,读路径无锁)。键空间有界
    (每分片默认 16 槽、上限 64),表满后新键样本丢弃计数——"未知即
    宽容"。样本与 0.6.1 测量包装同源:仅注入 wants_feedback() == true
    的调度器时才有流入,默认调度器行为与开销不变。Executor 新增
    get_feedback_snapshot()(诊断用),get_snapshot_text() 追加
    scheduling_feedback.* 段。新增 benchmark_feedback_aggregator
    (--json,验收线内置):record 快路径实测 23.8ns/task(预算
    ≤100ns);facade 端到端(提交→worker 反馈→聚合转发)与只计数
    调度器的差值在调度噪声内不可分辨(±40ns)。基准结果记录于
    docs/performance/m2_feedback_aggregator_results.md。

  • AdaptiveScheduler(M3,opt-in 自适应,DefaultScheduler 不变):
    新增公开头 include/kairo/adaptive_scheduler.hpp。复用 M1 pipeline
    产出 0.6.1 基线决策、内嵌 M2 FeedbackAggregator 作决策输入,实现
    roadmap §2.4 收窄后的三类可解释决策:

    • CPU/GPU 历史选择(CpuOrGpu):端到端时延 EWMA 两侧对比,
      双侧样本 ≥ min_samples 才采信历史(不足回退 0.6.1 启发式),
      切换需优于在用侧 (1 - hysteresis_margin)(防震荡);命中历史
      → RoutingReason::AdaptiveHistory + 诊断位 + detail 携带两侧
      EWMA 数值。submit_auto(CpuGpuTask) 补齐 CPU/GPU 两侧测量包装
      (此前该路径不产生反馈);RequireRequestedBackend 不做历史
      翻转;facade 对"启发式选 CPU + 非 AllowCpu 拒绝"规则豁免
      AdaptiveHistory 决策(启发式路径逐位不变)。
    • QoS 感知降载:按 QoS 类对 queue-wait 直方图做窗口差分后
      求 p99,连续 shed_breach_windows 个评估窗口超目标 → 开闸,对
      严格更低 QoS 的提交返回结构化拒绝(新增
      RoutingReason::LoadShedding + 诊断位);连续 shed_close_windows
      个恢复窗口才关闸(开/关对称滞回);证据不足 fail-open。与
      max_in_flight_tasks 硬上界共存。
    • QoS→priority 有界提升:IScheduler 新增
      effective_priority_for()(默认原样返回);长期超阈的 QoS 类
      默认优先级 +1 级(封顶 CRITICAL),显式 priority 永不被覆盖,
      被调整提交计数 priority_promoted_count。
      SchedulingMetrics 新增 adaptive_history_count /
      load_shedding_rejected_count / priority_promoted_count;Executor
      的 route_task 归一化与指标计数同步扩展。新增
      benchmark_adaptive_scheduler(验收线内置):route 纯策略路径配对差
      18.8ns(线 ≤150ns)、CpuOrGpu 冷路径 30.5ns(线 ≤250ns)、
      on_task_completed 转发 22.6ns(线 ≤150ns)、effective_priority_for
      0.74ns;降载场景 Interactive 探针端到端 p99 自适应 1.3-4.2ms vs
      DefaultScheduler 10.8-16.9ms(绑核配对,160-168 次结构化拒绝)。
      基准结果
      记录于 docs/performance/m3_adaptive_scheduler_results.md。

文档

  • 0.7.0 文档与发布同步(roadmap §2.5):docs/MIGRATION.md 新增
    "从 0.6.x 升级到 0.7.0"一节(无必需迁移:新头文件、
    IScheduler::effective_priority_for 默认实现、新 reason/诊断位/计数
    的穷举 switch 注意事项);docs/API.md §3.8 追加 0.7.0 开发快照
    (pipeline 组件、FeedbackAggregator、AdaptiveScheduler 决策语义与
    诊断接口)。网站新增中英文选型页"何时使用 AdaptiveScheduler"
    (website/{zh,en}/guides/adaptive-scheduling.md,重点覆盖震荡、
    冷启动、不可复现性),版本与迁移页新增 0.7.0 开发快照小节,API
    覆盖索引接入调度策略行,GPU 自动选择 / 执行模型 / 调度运行时教程
    页补开发快照交叉注记;docs/skill 两张调度卡(kairo-integration /
    kairo-maintainer)同步 0.7.0 自适应层与测试清单。

性能

  • M0 前后基准对比记录见
    docs/performance/m0_debt_paydown_results.md:两个既有热路径基准
    (benchmark_scheduling_paths / benchmark_thread_pool_hotpath)
    配对验证无回归;EDF dequeue 的关闭路径仅增加一次原子读。

kairo v0.6.1

Choose a tag to compare

@github-actions github-actions released this 06 Oct 17:09
7149a85

[0.6.1] - 2026-10-06

0.6.1 不扩张调度策略维度,对 0.6.0 建立的 Scheduling Runtime 边界做
稳定化、可观测性补全与工程验证。全部为 additive extension:不改变
提交协议、调度模型语义,也不包含任何自适应调度行为。设计文档:
docs/design/scheduling_runtime.md §6。

Scheduling Runtime 可观测性

  • 结构化路由决策:RoutingDecision 新增 status
    (Accepted / AcceptedDegraded / Rejected,接受/拒绝的权威判据)、
    diagnostics 位掩码(RoutingDiagnostics::AffinityMismatch /
    ResourceInfeasible)与稳定 reason code——过期 deadline 拒绝从泛化
    Rejected 细化为 DeadlineExpired,affinity 不相交从 detail 前缀
    升级为 AcceptedDegraded + AffinityMismatch。detail 仅供人阅读,
    不再是程序判断调度结果的唯一接口。新增
    routing_status_to_string() / routing_reason_to_string()。
  • 0.6.0 风格自定义调度器兼容:只设置拒绝类 reason、未设置 status
    的决策由 Executor::route_task() 归一化为 Rejected,行为不漂移。
  • 调度指标:Executor::get_scheduling_metrics() 返回
    SchedulingMetrics 单调计数(accepted / accepted_degraded /
    rejected / deadline_rejected / backend_unavailable_rejected /
    capacity_rejected / resource_rejected / affinity_mismatch /
    deadline_missed / feedback_reported)。计数在
    record_routing_decision 内以 relaxed 原子无条件累加,不受 CR-106
    观测开关影响,无需预先配置即可读取调度健康度。
  • 执行期反馈(measurement contract):SchedulingFeedback 扩展
    backend / executor_name / queue_wait_ns / execution_duration_ns /
    had_deadline / deadline_missed / failure_kind(success 时
    FailureKind::None);IScheduler::wants_feedback()(默认 false,
    DefaultScheduler 不消费)作为热路径开关——关闭时反馈通道零开销,
    开启时按任务付 2 次时钟采样 + 一次 worker 线程同步
    on_task_completed()(异常隔离)。覆盖实际开始执行的默认池任务;
    v0.7.0 前不实现任何基于反馈的自适应策略。

契约锁定与文档治理

  • deadline 准入边界锁定:严格已过(now > deadline)才拒绝,恰好相等
    接受;错过仍"记录 miss 但执行"。
  • capability snapshot 弱一致语义文档化:未知即宽容(跳过检查)、已知
    但不满足即结构化拒绝(ResourceInfeasible 诊断位)、admission
    feasibility 不等于 execution guarantee(TOCTOU 由后端执行失败报告)。
  • CpuGpuTask 的 heuristic-CPU + 非 AllowCpu fallback 组合在记录决策前
    修正为 Rejected,计数与最终投递结果一致(0.6.0 会先记录 Accepted
    再拒绝)。
  • 新增 scripts/check_docs_drift.sh 并接入 docs CI:扫描当前文档层的
    旧命名(executor:: / <executor/)、旧 CMake 用法、0.6.0 已删除
    API 与失效相对链接;历史快照(横幅标记)与 docs/archive/ 豁免。
    修复了扫描发现的 8 处真实漂移(README 失效链接、API.md 相对路径、
    design/performance 文档旧 API 名等)。

测试与基准

  • 新增 tests/test_scheduling_contract_v061.cpp(独立验证代理编写):
    结构化决策/指标/反馈断言、set_scheduler 时序与所有权、shutdown
    竞争、高并发 route()、deadline 边界与同时 deadline EDF 稳定性、
    capability 缺失退化、旧式拒绝归一化。
  • 新增 tests/benchmark_scheduling_paths.cpp:submit_auto 裸/全
    spec/feedback 包装、EDF 堆操作、DefaultScheduler route 纯策略 vs
    能力快照路径、能力快照采集的调度路径基线。

kairo v0.6.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 11:00
d9602ea

[0.6.0] - 2026-10-03

0.6.0 是破坏性变更窗口,包含三部分:项目更名(Executor → kairo)、历史
兼容层全面清理、以及 0.6.0 的核心主题 Scheduling Runtime——调度器与
执行器解耦,并建立统一的 deadline / QoS / affinity / resource 任务调度
模型。设计文档:docs/design/scheduling_runtime.md;迁移指南:
docs/MIGRATION.md 0.6.0 节。

项目更名(Executor → kairo)

项目边界已超出"执行器"单一概念,更名为 kairo;executor 保留为领域概念
(执行后端类名 Executor、ThreadPoolExecutor 等不变,挂于
kairo:: 命名空间):

  • 命名空间 executor:: → kairo::;include 路径 <executor/...> →
    <kairo/...>(目录 include/kairo/)。
  • CMake:find_package(kairo)、target kairo::kairo、产物 libkairo、
    选项/宏 EXECUTOR_* → KAIRO_*。
  • 打包 libkairo(deb/prefab/Windows zip)、CI artifact/release 命名、
    README/website/skill 品牌同步;项目图标更换为 docs/kairo.png。

兼容层清理(breaking)

历史版本为迁移期保留的弱 API 全部移除,可诊断的 Result 版本接管主名:

  • 7 对 facade API:initialize_ex → initialize(ExecutorResult)、
    wait_for_completion_ex → wait_for_completion(WaitResult)、
    register/start_realtime_task_ex、register/start_blocking_io_worker_ex、
    register_gpu_executor_ex 全部去后缀;旧 bool/void 版本删除。
  • IRealtimeExecutor::push_task() 从 void 改为返回 ExecutorResult
    (0.2.2 P-001 的 ABI 兼容约束解除);push_task_ex() 删除。
  • 定时器字符串 ID 体系删除:submit_delayed 返回 TimerSubmission、
    submit_periodic 返回 TimerHandle、cancel_task(task_id) 由
    TimerHandle::cancel() 取代;_with_handle 拼写随之消失。句柄版取消
    后记录保留为 Cancelled 终态(is_running=false,仍可查询),二次取消
    返回 AlreadyCancelled。
  • 4 参 legacy submit_auto、comm is_lock_free() 别名、
    RealtimeExecutorStatus::memory_locked 兼容字段删除。
  • 保留:StopToken/JThread 平台兼容层、submit_with_handle/
    submit_after_with_handle(TaskHandle 任务图族)。

Scheduling Runtime(核心)

  • IScheduler 解耦:路由/准入决策从 facade 内联代码移入可注入的
    IScheduler(Executor::set_scheduler()),默认实现 DefaultScheduler
    组合意图路由(TaskRouter)与调度模型约束。调度器只产出决策,投递仍经
    既有后端协议执行;热路径不变式(admission 先于 future、queued 诊断
    先于 enqueue、CR-106 惰性能力采集、PA-2 驻停代次唤醒)不回退。
  • deadline 模型:TaskBuilder::deadline() 从纯诊断升级为真实调度
    输入——同优先级内 EDF 排序;提交时已过期明确拒绝;开始执行时已错过
    记录 FailureKind::DeadlineMissed(deadline_missed_count),契约
    保持"取消是请求不是中断",错过的任务仍执行。
  • QoS 模型:QosClass{BestEffort, Standard, Interactive, Critical}
    在未显式设置 priority 时映射默认排队优先级;QoS 定位为排队优先级
    preset,不提供抢占、延迟界或实时性保证(确定性周期使用
    RealtimeQueue 意图 + 专用实时线程);严格优先级无 aging 的 CR-024
    契约文档化(BestEffort 可被饿死,防饿死在应用层拆分)。
  • affinity 模型:per-task advisory 亲和提示,与后端绑核集合不相交时
    在路由决策 detail 给出 AffinityMismatch 警告(不拒绝、不重绑线程)。
  • resource 模型:声明式 gpu_device/memory_bytes 与能力快照核对,
    不满足时以 BackendUnavailable/CapacityPressure 拒绝而非隐式降级;
    ExecutorCapability 新增绑核集合与 GPU 设备/内存维度。
  • 新增公开头:<kairo/scheduling.hpp>、<kairo/scheduler.hpp>;测试
    test_scheduling_runtime 32 项行为用例(EDF 排序、准入/错过、QoS 映射、
    affinity 诊断、resource 拒绝矩阵、调度器注入)。

executor v0.5.3

Choose a tag to compare

@github-actions github-actions released this 02 Oct 07:30
b785821

[0.5.3] - 2026-10-02

0.5.3 是稳定性与性能维护版本,公开 API 签名与既有语义保持兼容。主线是
2026-09-30 全量代码评审(docs/CODE_REVIEW_2026-09-30.md)四个阶段的落地:
P0 内存安全/挂死/数据竞争 9 项、P1 功能正确性 24 项、构建/打包 8 项、
热路径性能 10 项;随后定时器线程从 1kHz 轮询改造为事件驱动条件等待
(等待 CPU 降约 34 倍,periodic 抖动改善 10-27 倍)。每项修复均先以独立
复现测试确证再修复,并经独立验证通道复验。

修复与改进

代码评审 Phase 1(9 项 P0:内存安全/挂死/数据竞争,PR #202):

  • 单例退出 UAF(CR-001):~Executor 在单例模式下经 shutdown(true)
    排空默认执行器——在途 tracked 任务此前可触碰静态析构期已销毁的 facade
    成员(实测 SEGV)。
  • before_publish hook 数据竞争(CR-004):LockFreeTaskExecutor 钩子
    字段的普通写被生产者线程无同步读取(TSAN 2 处 data race + 空指针调用
    SEGV),改为原子不可变快照指针、trampoline 单次加载。
  • 参数绑定异常泄漏注册槽(CR-010/011):注册后绑定参数抛异常会永久
    泄漏取消注册表槽位、admission 计数与任务图节点(65536 次失败即耗尽
    注册表、任务图无界增长),两条 catch 路径均改为完整终态结算;非默认
    构造/不可赋值参数类型与 reference_wrapper 解包语义经 API 兼容探针
    保持不变。
  • SerialExecutionContext 生命周期 UAF(CR-012):submit_on 闭包改持
    shared_ptr<Shared>(pimpl + detach),上下文先于派发销毁不再使 worker
    永久阻塞于已释放互斥量;detached 发布以 ExecutorStopping 结算。
  • monitor 回调抛异常挂死 future(CR-020):任务体启动前 monitor 回调
    抛异常导致 future::get() 永久挂起,execute_task 的 catch 对未启动
    任务触发 on_timeout 结算。
  • 初始化失败后提交挂死(CR-022):初始化失败/回滚后接受的提交永不
    执行(future 挂死),task_timeout_ms 锁外读取与 initialize() 竞争。
    三条 submit 路径改锁内检查 initialized_,超时配置锁内读取。
  • CUDA 启动失败队列滞留(CR-002):start() 中途失败留下未消费任务,
    后续 stop() 在 wait_for_completion 永久挂起;失败路径以
    set_exception 排空队列,未启动 worker 时排空谓词直接退出。
  • OpenCL 重启泄漏(CR-003):restart 覆盖 context_(每次重启泄漏)
    并无界追加 queues_;重初始化先回收上一代(存活队列逐一 clFinish)
    再清理。
  • 环检测递归爆栈(CR-052):任务图环检测 DFS 持写锁递归,约 4k 深度
    即 SIGSEGV(256KB 栈);改为显式栈迭代 DFS。

代码评审 Phase 2(24 项 P1 功能正确性,PR #203),要点:

  • KeepLatest/DropOldest 竞争下丢最新值(CR-040):位移路径有界重试,
    2s 观测 20999 次虚假拒绝 → 0。
  • worker park 丢唤醒(CR-005):park 改 fetch_or;旧代码可把已入队
    任务搁置到下一次 push(秒级 P99 尖刺),修复后稳定。
  • GPU 内存池对齐破坏(CR-060):块头部不再破坏 256B 对齐(float4
    访问出错)。
  • GPU 完成集无界增长(CR-062):+72MB/百万任务 → +0.2MB;
    remove_task 不再留下可运行的依赖者。
  • GPU optimizer 配置数据竞争(CR-063):TSAN 10/10/9 处报告 → 0。
  • 其余项覆盖线程池、通信原语、GPU 后端、监控与平台工具,全表见评审
    文档 "Phase 2 修复执行记录"。

诊断顺序与 CI 稳定性(PR #204):

  • queued 诊断先于 enqueue(NN-12):三条 submit 路径此前在 enqueue +
    唤醒后锁外补记 record_task_queued,worker 可在补记前取走任务执行,
    诊断条目以 Queued 状态在任务已运行时创建,快照 in_flight_state_counts
    缺 Running 键导致 map::at abort(注入窗口 10/10 重现)。现移入
    mutex_ 临界区、enqueue 之前,建立 queued→start→complete 严格顺序,
    顺带消除 complete 先于补记时诊断表滞留僵尸 Queued 条目;锁序
    pool.mutex_ → monitor.mutex_ 保持单向。
  • 测试加固:快照测试改 wait_in_flight_drained()(future-vs-cleanup
    竞态,满载排水 p99 3.0ms、26 倍裕量);偷取测试竞争窗口改"批次耗尽即
    收尾 + 墙钟预算"。

性能

热路径优化(评审 Phase 4,10 项,PR #206;结论均以同参 Release 多轮
中位数口径测量)
:

  • 路由惰性能力采集(CR-106):策略路径不再锁 5 把注册表,观测写入加
    快速开关,无回调时移动入库;submit_auto vs submit 中位差距
    +19.9% → +11.6%。
  • 完成通知等待者门控(CR-108):无等待者时每任务 2 次 notify_all
    全部消失。
  • 等待轮询通知化(CR-109):try_wait_for_completion 从 10ms 盲轮询
    (300s = 3 万次全量扫队列)改为通知驱动谓词等待 + 50ms 兜底分片。
  • 提交路径单次分配(CR-110):submit 的 promise+ready 双包装合并
    单次堆分配。
  • 派发器锁分配消除(CR-112):三处 unique_ptr<shared_lock> 改
    std::optional,每次 dispatch 免一次堆分配。
  • lockfree 队列 hook 快速路径(CR-121)+ 批量便签(CR-122):常态推送
    零 shared_ptr 原子读(旧 libstdc++ 走内部锁池);批量路径 thread_local
    便签免反复分配。
  • GPU 参数缓存 O(1) 侵入式 LRU(CR-151):替换 O(n) 扫描;更新已有
    key 不再误逐热点。
  • 测量口径更正与不改语义决定(CR-102/CR-135):旧基准为 O2 TU 链 O0
    库的混合优化口径,评审"基线 65-70%"系该产物(同参 Release 真实差距约
    +20% 内);retention 高水位摊销被精确上界契约测试否决,扫描深度插桩
    证明恒为 1,语义不变。

定时器事件驱动改造(PR #207,CR-135 后续):

  • 1kHz 轮询 → 条件变量等待:schedule/periodic/reschedule/stop 持锁
    bump schedule_epoch_ 并 notify,调度线程精确睡到堆顶 deadline(堆空
    100ms 兜底上界)。等待 CPU 从恒定 0.7-1.0% 单核降至 0.024%(约 34 倍,
    收益主体是能耗)。显式 wait_until(system_clock) 规避 GCC ≥ 10 的
    wait_for(duration)/wait_until(steady_clock) 均映射到
    pthread_cond_clockwait、gcc-11 libtsan 不拦截(PR101978)的误报缺口;
    CI TSAN job(g++-11,即约束工具链)补入 test_timer_handle 作为权威
    门禁。取消语义不变:request_cancel 仍不唤醒(stale-entry lazy-deletion
    契约)。
  • periodic 网格锚定:next = 上一 deadline + P(错过不追补)取代
    now + P——旧锚定把唤醒过冲逐周期累积成漂移,旧 1ms 轮询的网格量化
    恰好掩盖了它。periodic 抖动 avg 569-642µs → -47~+55µs(改善 10-27 倍)。

构建与打包(评审 Phase 3,8 项,PR #205)

  • 覆盖率插桩真正生效(CR-080):库插桩改 executor_apply_coverage_to_target()
    函数式显式调用(旧版 include 期 if(TARGET executor) 恒假,库从未产出
    覆盖数据、报告静默失真);插桩库的消费方经 INTERFACE 链接选项继承
    --coverage,独立测试目标不再缺 gcov 运行时。
  • 版本单一来源(CR-085):6 个打包脚本默认值改从 project(VERSION)
    提取;新增生成的 executor/version.hpp(构建树 BUILD_INTERFACE 与
    install 双路可达)。
  • Sanitizer 配置治理(CR-083):Sanitizers.cmake 无条件 include;TSAN
    独立于 EXECUTOR_ENABLE_SANITIZERS 总开关(CI Release+TSAN job 路径
    保留);ASAN/TSAN 显式同开在配置期 FATAL_ERROR。
  • 安装树完整性(CR-084):executor/util/ 纳入安装;GPU 后端头 6 处
    源码树相对包含(安装树必断链)改 <executor/...>;新增
    install_headers_smoke ctest(临时 prefix 安装 + 全部已安装头探针编译)。
  • Windows/共享库守卫(CR-081/082/086):共享库守卫扩到
    MSVC OR (WIN32 AND NOT MINGW)(覆盖 clang 工具链);package_windows.ps1
    撤销多余 Split-Path(包内文档静默缺失);build_windows.ps1 开关透传
    (旧版硬编码 OFF 无视入参)。
  • ODR 违例结构性消除(NN-01):ThreadPool 测试钩子无条件参与类布局,
    EXECUTOR_THREAD_POOL_TEST_HOOKS 不再影响布局——混合宏 TU ↔ 库的
    ASAN stack-buffer-overflow 根因消除。

文档

  • 新增 docs/CODE_REVIEW_2026-09-30.md:全量代码评审与四阶段修复执行
    记录——每项缺陷的复现证据、修复方案与复验结论;含三项评审前提被测试
    推翻(CR-051/CR-104/CR-102)与一项被测量口径更正(CR-106)的记录。

executor v0.5.2

Choose a tag to compare

@github-actions github-actions released this 28 Sep 09:33
6cae4ea

[0.5.2] - 2026-09-28

0.5.2 以 dependency-driven scheduling 为主线:submit_after 的依赖等待从
"任务立即入队、wrapper 在 worker 上等待条件变量"演进为调度侧唤醒——依赖
未就绪的任务驻留任务图节点、不占用 worker,依赖终态定向级联出队;补全
parked 超时(提交即起算)与 shutdown 终局结算语义,退役 task_graph_cv_
及其惊群唤醒,新增监控 Queued 补记与诊断接口。既有公开提交 API 兼容;
闭包墓地诊断接口 closure_graveyard_size() 为唯一新增公开方法。

新增

  • dependency-driven scheduling 第三阶段(PR-3,v0.5.2 主线收口,设计见
    docs/design/dependency_driven_scheduling.md)
    :
    • task_graph_cv_ 退役:依赖图任务运行时不再有任何依赖检查与
      条件变量等待(PR-1 起 parked 任务仅在依赖全部成功后入队,终态不可逆),
      4 处 notify_all 惊群唤醒全部删除——每 terminal 唤醒从 O(等待者)
      降为 O(1) 定向入队。
    • 监控 Queued 补记:parked 任务出队入执行器时补记 Queued
      生命周期,观测链完整为 DependencyBlocked → Queued → Running。
    • closure 墓地观测与终局清空:新增 closure_graveyard_size()
      诊断接口;shutdown 终局清空墓地释放常驻引用。
    • PA-6 验收基准:新增 tests/benchmark_task_graph_paths
      (tracked 提交吞吐 1/2/4/8 生产者、parked fan-out 释放延迟、依赖链
      每跳成本、墓地规模);PA-6 数据回填 performance_audit 台账,
      "分桶锁"备选确认不再需要。
  • dependency-driven scheduling 第二阶段(PR-2,v0.5.2 主线,设计见
    docs/design/dependency_driven_scheduling.md)
    :
    • D1 parked 超时:queued soft timeout 自提交时刻起算,parked 期间
      经 facade 一次性定时器(时长取 ExecutorConfig::task_timeout_ms,
      0 = 不启用维持既有行为)触发,与池队列计时器经 phase CAS 仲裁恰好
      一个赢家;parked 获胜即失败结算并级联下游。定时器线程按需启动
      (全新 facade 无需先提交 delayed/periodic 预热);输家/赢家闭包的
      promise/state 捕获转入 facade 墓地延迟析构,消除定时器线程与消费者
      使用异常对象之间的析构竞争(TSAN 实证);record_task_timeout
      先于自身 future 结算(统计可见性与级联顺序同一不变式)。
    • D2 shutdown 终局结算:shutdown 返回前对全部仍 parked(依赖永不
      就绪)的节点统一失败结算,future 不悬空、admission/registry/in-flight
      全部释放;serial 派发被池丢弃时 TicketGuard 同步补图终态,parked
      下游即时级联。
    • serial dispatch 结算顺序对齐:submit_on 全部终态路径 drain bag 化
      (on_timeout/成功/协作取消/失败/context 拒绝),失败统计先于级联
      写入——与 tracked 路径同一观测不变式。
    • retention 交互与 admission 四路径(依赖失败/超时/取消/shutdown)
      恰好一次释放的验收测试。
  • dependency-driven scheduling 第一阶段(PR-1,v0.5.2 主线,设计见
    docs/design/dependency_driven_scheduling.md)
    :submit_after /
    submit_after_with_handle 从"任务立即入队、wrapper 在 worker 上等
    条件变量"演进为"依赖未就绪不入队"——parked 载荷驻留任务图节点
    (提交时定格 wrapper/priority/执行器快照),依赖终态经
    resolve_task_graph_dependents_locked 级联:全部成功按原 priority
    调度侧出队,任一失败即时结算依赖异常(任务不占 worker)。
    worker 占用与宽依赖饿死/挂死窗口消除(新增免饿死回归测试,旧实现
    在该场景挂死);unmet_count 驱动定向出队,替代对全部等待者的
    notify_all 惊群(条件变量本体按计划 PR-3 退役)。

修复与改进

  • facade 析构与孤池 worker 的 UAF 闭环(既有窗口,PR-1 时序使其暴露):
    stop(false) 将池交给 detached 终结线程后,manager 撤下句柄,后续
    shutdown(true)(含 ~Executor 路径)此前会完全跳过等待,孤池 worker
    收尾(failure 面板/monitor/registry 写入)可与 facade/manager 析构并发
    (TSAN 实证 heap-use-after-free)。现改为 retired 保活 + 终局排空:
    executor 退休池存入 retired_pools_、manager 停机执行器存入
    retired_async_executors_,任何 shutdown(true) 先等退休池 worker 全部
    join 再放行析构;stop(false) 立即返回契约不变。
  • 失败统计先于依赖级联:tracked 任务异常路径中 record_task_exception
    提前到级联结算之前——dependent future 就绪时失败面板计数保证可见
    (满载下 8/20 观测窗口,修复后 0/40)。

文档

  • 待办账实清理(v0.5.x 阶段 21 第一项):对 docs/todolists/ 15 份计划文档
    逐项审计核实(约 326 个未勾项 → 186,且剩余均为真遗留、显式门控(⏸)或
    可重跑模板)。要点:主清单阶段 20 P1/P2 回填勾选(随 0.5.0 合入)并新增
    阶段 21(dependency-driven scheduling,承接 performance_audit PA-6 的
    调度侧唤醒深化);lockfree_queue_optimization §6.2/§6.3 三处失实勾选勘误;
    gpu_todolist 约 70 项回填勾选,§3.5 "pinned memory / optimizer" 两处已勾项
    经审计证伪加勘误注记(对应 PA-30/PA-31);android/client/mira 三份反馈计划
    约 26 项漏勾回填、已决待决项回填,外部门控项(big.LITTLE 真机、heyaki
    M6/M7、Mira 回填)显式标注;发布前人工核对项迁入 docs/RELEASE_CHECKLIST.md;
    android 两项已定决策回写 docs/design/android_port.md 待决项;修复
    website/.vitepress/config.mjs 中英导航版本标签滞后(v0.4.0 → v0.5.0)。

修复与改进

  • #194 benchmark_thread_pool_hotpath harness 数据竞争修复:Phase 2 延迟采样的
    任务闭包原先并发 push_back 同一 per-producer std::vector(同一 producer 的
    任务可被任意 worker 执行),TSAN 构建下确定性报 data race 并因 vector 内部状态
    损坏挂死(30s ctest 超时,重跑仍不终止)。现改为每样本一个预分配槽位,由
    (producer, sample index) 唯一寻址:任务闭包只写自己独占的槽,采样路径零共享
    容器写入;槽位在 shutdown(true) join 全部 worker 后单线程读取。修复后 TSAN
    构建对该 benchmark 0 warning;Phase 1 吞吐压测的插桩减速(~20x,实测 220-276s)
    通过 TSAN 构建下单独放宽 ctest 超时到 600s 收敛(库代码无涉)。
  • #187 残余窗口封口(批量预留误取消):v0.5.0 的倒序预留 + BatchWriting
    逃逸把误取消窗口缩到极窄,但在 2-vCPU CI runner 的 gcc-11 Release TSAN 下,
    写入循环中段仍可被 scan-ahead 消费者在生产者线程被抢占期间按 64-yield 预算
    误判停滞(test_batch_integration 间歇失败)。消费者侧取消预算现按认领批量
    规模缩放(reservation_wait_yields_ × min(claimed, 1024),claimed 即
    enqueue_pos_ 单次 CAS 认领的槽数):健康批量生产者不再可能被误杀;真停滞
    恢复延迟按批量线性、有界(最坏 64×1024 次 yield,亚秒级),停滞契约测试
    (小批量 + hook 阻塞)不受影响。

executor v0.5.0

Choose a tag to compare

@github-actions github-actions released this 13 Sep 06:22
2ae4fc8

[0.5.0] - 2026-09-13

0.5.0 以任务生命周期语义与跨平台落地为主线:facade 新增任务级协作取消与可取消、
可重排的定时句柄,串行执行上下文与总量有界 admission 转正;Android 适配一期完成
CPU-only 交叉编译与 ARM64 验证;2026-09 性能审查的 P1(线程池提交热路径)与
P2(无锁组件兑现)两阶段重构合入,提交吞吐与 RT jitter 显著改善;停机/生命周期
竞态(P-001~P-008)与 TSAN 可见的数据竞争面收敛。既有主要公开调用方式保持兼容;
ExecutorSnapshot schema 2 → 3(纯新增字段)。

任务协作取消与定时句柄(客户端反馈台账 P1-2/P1-3 收敛,设计见
docs/design/task_cancellation_and_timers.md):facade 新增任务级协作取消与可取消、
可重排的定时句柄;取消是协作请求而非抢占,取消计数进入独立生命周期字段而非
failure 体系。

串行执行上下文与总量有界 admission(Mira 台账 EXE-20260830-001/002/003 收敛,设计见
docs/design/serial_execution_context.md、docs/design/bounded_admission.md):
submit_on/submit_on_with_handle 的 facade wrapper 重构为非阻塞共享状态;
max_in_flight_tasks 为默认异步提交提供跨 scheduler 与本地队列的总量上限。

新增

  • 任务级协作取消(C1):新增 include/executor/task_cancellation.hpp
    (TaskCancelled / TaskCancellationReason / TaskCancellationResponse /
    CancellationStatus)。submit_cancellable / submit_cancellable_priority /
    submit_cancellable_after 把 StopToken 注入为 callable 首参数;
    request_task_cancel(const TaskHandle&) 提供排队取消与运行中协作请求,
    幂等且不写 failure 事件;submit_with_handle / submit_after_with_handle
    天然获得排队取消能力;取消 registry 有界(默认 65536,
    set_cancellation_registry_capacity() 可调),容量耗尽明确拒绝。
  • 定时句柄(T1):新增 include/executor/timer.hpp(TimerHandle /
    ScopedTimerHandle / TimerStatus / TimerOperationResult)。
    submit_delayed_with_handle / submit_delayed_cancellable_with_handle /
    submit_periodic_with_handle / submit_periodic_cancellable_with_handle
    提供取消、重排与状态查询;内部定时器改为 registry + generation heap,
    变更 1ms 内可见的 steady 时钟分片等待(5ms 延迟任务的平均到期误差从约 5.5ms
    降至约 0.9ms;不用 condition_variable 定时等待,规避 gcc-11 libtsan 对
    pthread_cond_clockwait 未拦截导致的 double-lock 误报),
    stale entry 有界压缩;终态 record 只保留有界元数据。
  • 定时器互操作指南(S1):新增 docs/external_event_loop_interop.md 与可编译
    示例 examples/event_loop_interop.cpp(托管事件循环、strand 延续盲区纪律、
    PhaseGate 批次收尾);中英文网站同步上线指南页。
  • 监控扩展:ExecutorSnapshot schema 2 → 3,新增 cancellation
    (CancellationStatus)与 timers(TimerStatusSummary)独立字段与快照文本行;
    Executor::get_cancellation_status() / get_timer_status_summary() 查询入口。
  • 教程与测试:新增教程 examples/tutorial/13_cancellation_and_timers.cpp、
    tests/test_task_cancellation.cpp、tests/test_timer_handle.cpp、文档一致性测试
    tests/test_api_doc_cancellation_fields.cpp,以及整库
    EXECUTOR_STOP_TOKEN_FORCE_FALLBACK 强制实例化的
    tests/test_task_cancellation_fallback.cpp。
  • comm 指引(G1 轻量项):中英文"如何选择通信组件"指南新增
    "什么时候允许裸回调"一节,明确裸 std::function 回调的适用边界。
  • 串行执行上下文(S2):新增 include/executor/serial_execution_context.hpp
    (SerialExecutionContext,post/reserve/post_reserved/abandon/shutdown,
    FIFO ticket 语义)。Executor::submit_on / submit_on_with_handle 在其上提供
    严格按提交顺序结算的 std::future<T> / TimerSubmission<T>;facade wrapper 为
    非阻塞共享状态实现(派发/结算分离),多 worker 下不再互相饥饿(两 worker ×
    10,000 突发约 1s 内全部结算),外部事件循环互操作见
    docs/external_event_loop_interop.md。
  • 总量有界 admission(A1):ExecutorConfig::max_in_flight_tasks(默认 0 =
    不启用、零热路径开销)为 facade 默认异步提交(普通 / priority / tracked /
    cancellable / batch / submit_on*)提供总在途上限;达到上限时提交不抛出,
    future 立即以 CapacityExhaustedException 就绪,FailureKind::CapacityExhausted
    事件与 capacity_exhausted_count 计数可观察;运行期 set_max_in_flight_tasks() /
    get_in_flight_submissions() / get_max_in_flight_tasks() 可调可查。

性能

  • 无锁组件兑现与 RT 优先级反转消除(性能审查 PA-5/7/8,2026-09 收敛计划
    阶段 P2)
    :ObjectPool 改 tagged Treiber 索引 freelist((tag:32 | index:32) 单字 head,ABA 由 tag 封闭;消费者 release_bulk 整链单 CAS
    splice;双重释放检测改为 per-node state CAS,语义不变)——
    LockFreeTaskExecutor 提交路径与 RT 线程逐任务 release 不再共享互斥锁,
    RT 路径优先级反转面消除;LockFreeQueue 消费侧 MPMC 化(前沿连续
    Published run 单 CAS 认领),LockFreeWorkerQueue 的 pop/steal/size 去
    consume_mx_(steal 与 pop 同为 FIFO 最老端,恰好一次交付),size()
    改无锁近似值;LockFree worker 空闲从 1µs-sleep 永久轮询(约 10⁶
    syscall/s/核)改为「PAUSE → yield → 10µs-sleep 缓冲带 → futex 驻停」,
    驻停编码进 32 位 wake_seq_(bit0=驻停位 + 唤醒计数,生产者 push 后
    无条件 fetch_add(2)、返回值带驻停位才 notify_one,忙碌路径零
    syscall),空闲 executor 进程 CPU 实测 0.0ms/500ms。实现期修复两个
    深挖出的并发陷阱(条件唤醒标志被 StoreLoad 重排打穿致挂死;CAS 循环
    带陈旧期望值重试致偶发线程饿死 20 秒+)。基准(同机同条件 3 次取中位):
    mpsc 吞吐 1P +86%、8P +289%、16P +482%、32P +399%;RT 执行器提交延迟
    -21%;RT 1ms 周期 jitter p50 78.7→16.8µs;已知取舍:2-4 生产者 mpsc
    吞吐 -23%~-24%(Treiber 单链低生产者数下的缓存行往返,详见计划文档
    P2 小节归因实验与后续条目)。新增 test_object_pool_lockfree_stress
    (多生产者锤击 + RT 延迟分布 + 空闲 CPU 守护 + 驻停唤醒守护)。设计
    推导与基准全表见
    docs/todolists/performance_audit_2026-09_plan.md 阶段 P2 小节。
  • 线程池提交热路径重构(性能审查 PA-1/2/3/4、PA-9/13/17,2026-09 收敛计划
    阶段 P1)
    :worker 空闲驻停从「全局 mutex_ + condition_ 重谓词(谓词内做
    steal/dequeue,含堆分配与排序)」改为 32 位驻停代次计数 + C++20
    std::atomic::wait(Linux futex 直达);提交路径单任务 notify_one +
    worker 接力唤醒(并行度指数恢复,惊群消除),批次 notify_all;Task 全链路
    (enqueue → dequeue → dispatch → 本地队列 → pop)改 unique_ptr 所有权/字段级
    移动,消除逐跳 std::function/string/vector 复制;dispatch_batch 消除每次
    派发的 4-6 次堆分配(成员便签 + 计数排序分段);local_queues_ 去除
    libstdc++ atomic_load(shared_ptr*) 库级自旋锁(改为读写锁保护下的裸指针
    快照);steal victim 选择无分配化(LoadBalancer::highest_load_victim);
    should_exit 原子空集快速路径。停机正确性同步加固:worker 的 stop_ 退出加
    「退出守门」(持 dispatcher 锁复核代次),排除任务处于搬运途中被永久滞留的
    窗口。基准(14 核桌面,gcc 13 Release,3 次取中位):单生产者提交吞吐
    125.5k → 565.4k tasks/s(4.5x),e2e 3.5x,多生产者(2-32 线程)2.2-4.7x
    且扩展曲线平坦化,直连 ThreadPool 的单生产者吞吐 13.5x、唤醒 p99(4T+)
    3-5x 改善。新增 benchmark_thread_pool_hotpath(多生产者争用吞吐 +
    wake-to-exec 延迟分布)。设计说明(32 位 futex 前置条件、代次采样时机、
    接力唤醒与退出守门的推导)见
    docs/todolists/performance_audit_2026-09_plan.md 阶段 P1 小节。

修复与改进

  • P-001/P-002(停机竞态):LockFreeTaskExecutor 与 RealtimeThreadExecutor
    以单原子准入门闩消除停机与提交交错的生命周期竞态(PR #180);worker 线程内
    自停止语义与 stop_and_join() 返回值契约同步澄清。
  • P-003(LockFree 池容量):对象池按取整后的环容量统一分配——请求容量 5
    (环取整为 8)时可用槽位 7,池与 push_tasks_batch 上限一致,非 2 的幂配置
    不再让 failed_pushes / queue_full_rejections 失真。
  • P-004(进程内存锁租约):util::ProcessMemoryLockLease 引用计数管理
    mlockall/munlockall——行为变化:最后一个持有租约的实时执行器停止时
    才解除进程锁;与进程内其他 mlockall 使用方共存更安全。
  • P-008(Windows 处理器组):cpu_affinity 支持超过 64 逻辑 CPU 的
    处理器组编号(g*64+序号),跨组配置明确拒绝(PR #181)。
  • TSAN 收尾(issue #185–#188):LockFreeQueue::push_batch_exact 的批量预留
    会被消费者"停滞生产者恢复"启发式误取消(TSAN 构建下空环确定性失败)——预留改
    倒序使前沿槽可取消窗口缩至 O(1),cancel_reservation 增加 BatchWriting 逃逸,
    停滞恢复契约保持不变;~TaskMonitor 析构先取 mutex_ 再成员析构,与最后一个
    持锁读者建立 happens-before(消除 shutdown/析构路径 TSAN 报告与潜在 UAF);
    test_lockfree_mpsc 测试自身同步域修复;benchmark 测试 RUN_SERIAL +
    sanitizer 构建下延迟断言豁免;TSAN CI 子集补 test_lockfree_mpsc /
    test_batch_integration / test_executor_manager。
  • P-006/P-007(可观察性):ThreadPool::get_status() 空闲线程数饱和语义
    与 resizer 竞态修复;GPU validate_memory_range 拒绝外部缓冲区,无锁队列
    size()/empty() 近似语义钉住回归测试。
  • 测试与 CI:admission/serial 独立测试 NDEBUG 安全化;慢 CI runner 上
    计数与 tick 轮询有界化;forced-fallback 目标从全源码清单构建。

变更

  • shutdown 清理未到期 delayed 任务:future 异常由
    std::runtime_error("Timer stopped...") + SubmitRejected 事件改为
    TaskCancelled(Shutdown),不再记录 failure 事件;可观察性转移到定时计数。
  • ExecutorSnapshot::schema_version 2 → 3(纯新增字段);解析快照文本的下游
    工具需按新 schema 更新(迁移说明见 docs/MIGRATION.md)。

Android 适配一期

Android 适配一期:核心库可在 NDK 工具链下以 CPU-only 配置交叉编译为静态库/共享库,
并纳入官方模拟器与真实 ARM64 runner 的验证流程。Android 上的线程优先级、CPU 亲和性、
mlockall 与 timer slack 均保持 best-effort,不承诺硬实时;CUDA/OpenCL 不进入一期。

新增

  • Android CPU-only 构建支持:新增 if(ANDROID) CMake 平台分支,bionic 下不再错误
    链接 librt,也不导出 libatomic;Android 构建默认关闭 GPU/CUDA,用户仍可显式覆盖。
  • 便携 StopToken/JThread 兼容层:新增 include/executor/stop_token.hpp。桌面平台
    executor::StopToken 是 std::stop_token 别名,保持既有 override 源码与 ABI 兼容;
    Android libc++ 未启用 jthread 时使用自有 StopSource / StopToken / detail::JThread。
  • Android 线程与 affinity 默认值:bionic 下使用 sched_setaffinity /
    sched_getaffinity;默认线程池上限为 4,自动 affinity 来自 cgroup 允许 cpuset;
    短周期实时线程不再自动申请 SCHED_FIFO。
  • Android 构建与设备脚本:新增 scripts/build_android.sh、
    scripts/run_android_tests.sh、scripts/capture_android_device_info.sh,以及
    tests/android_smoke.cpp 等无 GTest standalone 测试。
  • Android CI:新增 NDK r26c / r28b 交叉编译 workflow;新增手动触发的
    arm64-concurrency workflow,覆盖 4 核、单核 pinned、ASan/UBSan 和可配置 MPSC soak。
  • Android 打包与平台文档:新增 docs/PACKAGE_ANDROID.md,覆盖 NDK CMake、AGP、
    c++_shared 打包、JNI shutdown 生命周期与 Prefab/AAR 模板;中英文网站首页、构建页
    与平台部署核对页同步补充 Android CPU-only 能力边界。

修复与改进

  • 修复 test_multithread_mpsc 在慢速 ARM64 模拟环境下消费者过早退出导致误报的测试逻辑。
  • Android 下实时调优路径统一为 best-effort:priority / affinity / mlock / timer slack
    失败只写入状态字段,不改变任务接受结果。
  • 为 Android 平台裁剪 NDK clang 不支持的 warning 选项,并守卫仅适用于 desktop Linux
    的 /proc 测试。
  • 修复 P-260816-001:ExecutorManager::shutdown() 不再在持有
    default_async_mutex_ 时执行默认执行器的阻塞排空(stop(wait_for_tasks) /
    wait_for_completion() 含 worker join)。此前池内任务在排空期间再入
    submit() / 状态查询等持锁读路径会与 shutdown 互相等待形成自死锁;现在改为
    锁内置闩并快照执行器、锁外排空,置闩后读路径立即走拒绝分支,与 ThreadPool
    自身"先停止接收新任务,再等待已接受任务完成"的关停顺序对齐。并发 shutdown
    调用者通过新增的条件变量等待排空完成,保持"第二个调用者等第一个排空结束后
    才返回"的旧语义。新增回归测试 tests/test_shutdown_drain_reentrancy.cpp
    (旧实现在该测试下确定性死锁)。
  • 修复 P-260816-002(H1):Executor 定时器线程启停竞态。旧实现先原子置位
    timer_running_ 再创建线程并给 timer_thread_ 赋值,并发 shutdown 会在成员尚未
    赋值时读取它(数据竞争 UB)并跳过 join;随后赋值出的 joinable 线程成员在析构时触发
    std::terminate,竞态窗口内提交的延迟任务 future 永久悬挂。现在:timer_thread_ /
    timer_state_ / 测试工厂由 timer_thread_mutex_ 保护,赋值完成后才置位运行标志;
    每代线程持有独立的停止标志,停止只对本代置位(join 期间并发重启不会复活旧线程,
    join 必定返回);join 在锁外执行。submit_delayed 在入队临界区内检查停止位,
    消除"入队后无人处理"的悬挂 future;set_timer_thread_factory_for_test 同步化。
    新增回归测试 tests/test_timer_thread_lifecycle_race.cpp(旧实现下延迟任务
    future 永久悬挂 / std::terminate,测试确定性命中)。

验证

  • 官方 Android 模拟器(API 30 x86_64,KVM):6/6 standalone 测试通过。
  • qemu-user + NDK bionic 静态 ARM64:6/6 测试通过。
  • GitHub ARM64 runner(Neoverse-N2,4 核):6/6、单核 pinned、ASan/UBSan、600 秒
    MPSC soak 均通过;结果见 docs/performance/android_a3_validation.md。
  • big.LITTLE Android 真机验证已登记为发布前 gate,正式版本不得在未完成该项时宣称
    已在 big.LITTLE 设备验证。
  • P-260816-001 修复验证:树内 Debug 构建 105/105 ctest 通过(除 benchmark 标签外);
    关停/生命周期相关测试(test_shutdown_drain_reentrancy、`test_c...
Read more

v0.4.0

Choose a tag to compare

@Linductor-alkaid Linductor-alkaid released this 13 Aug 06:36

[0.4.0] - 2026-08-13

0.4.0 聚焦通信与并发执行路径的确定性边界:核心通信组件采用构造期固定存储和原子同步,新增进程内 Topic 扇出、LET 阶段通信、实时分配诊断及延迟分位数观测;任务图句柄保留和线程池真实扩缩容也获得明确的容量与并发语义。既有主要公开调用方式保持兼容,但“同步无锁”仅描述组件内部原子与固定存储,完整实时性仍须由调用方在目标环境验证。

新增

  • 进程内 Topic / Subscription:新增 comm::Topic<T> 与 move-only RAII TopicSubscription<T>,将订阅后的事件扇出到每个订阅者的独立有界 FIFO;发布结果报告匹配、成功和拒绝订阅数,逐订阅者保留独立 drop policy、统计、回调和关闭唤醒语义。该原语明确不提供网络传输、重放、可靠确认或硬实时保证。
  • LET 阶段通信契约:PhaseGate、DoubleBuffer 与 LatestMailbox 新增可选的 phase-bound LET 模式。绑定后,发布仅发生在当前相位,读取仅暴露上一完成相位的数据;相位切换会拒绝活跃读写,避免跨周期读取或写入。
  • 实时内存分配诊断:新增 comm::RealtimeAllocationGuard、RealtimeAllocationViolationPolicy 和线程局部统计,可记录受保护实时路径中的分配次数、字节数、组件与阶段;Linux 构建可通过 EXECUTOR_ENABLE_REALTIME_ALLOCATION_GUARD 启用,RealtimeThreadConfig::enable_allocation_guard 控制周期回调的 opt-in 诊断。
  • 通信延迟分位数:CommStats 增加固定大小延迟直方图及近似 p50_latency、p99_latency,同时保留累计、平均和最大延迟统计。
  • 有界任务图句柄保留:ExecutorConfig::task_graph_retention_capacity 和对应运行时设置 API 控制终态 TaskHandle 的保留上限。被淘汰的句柄会明确拒绝为过期;仍被活跃依赖链引用的节点不会提前淘汰。
  • 线程池真实扩缩容:ThreadPool::resize() 与 ThreadPoolResizer 现创建或移除真实 worker,且仅接受初始化配置的线程数范围;缩容前迁移本地队列任务并 join 被移除 worker,返回时状态稳定。

修复与改进

  • 通信同步核心无锁化:MpscChannel / RealtimeChannel 改为构造期预分配的有界 MPSC 节点池,
    LatestMailbox / 未绑定 DoubleBuffer 改为固定 reader-pin 快照槽,PhaseGate / Sequencer
    改为原子状态核心;新增同步原子 lock-free 查询与构造期平台校验。该保证不覆盖 payload、callback、
    时钟、缺页或 OS 调度,Topic fan-out 仍属于 mutex 与动态分配支持的非实时控制面。
  • 线程池扩缩容并发安全:本地 worker 队列改以原子发布的 shared_ptr 快照访问,调度、窃取与 resize 通过读写锁协调,避免队列替换期间的悬空访问和 UAF;shutdown 与 resize 的 join 路径也已串行化。
  • 任务调度边界:移除 TaskDispatcher 的旧引用构造路径;空本地队列快照不会从调度器取走任务或发生越界访问。
  • 实时契约实现边界:LET 绑定要求固定双缓冲容量和不抛异常的复制语义;每个相位只允许一次发布,缺失上一相位数据或相位转换中读取会返回明确的通信错误。
  • 兼容性:调整 C++20 实现以兼容 GCC 10(项目仍建议使用 GCC 11 或更高版本)。

文档与测试

  • 更新中英文 README、API、通信设计文档、教程站点与 sitemap,补充 LET 状态/相位、通信选择、延迟观测和失败可观测性示例说明。
  • 新增 Topic fan-out/独立背压/并发生命周期、通信实时内存、LET PhaseGate、邮箱与双缓冲、任务图保留/过期语义的测试;扩展线程池扩缩容、调度 fallback 与并发 UAF 回归测试,并约束扩缩容压力用例的工作负载。
  • 新增面向使用者的 executor-integration 渐进式接入指南,以及面向维护者的能力索引与维护参考。