算法
算法层是白皮书进入“可操作精度”的地方。它不引入新的产品面,而是把今天维护中的 stat / filter 能力解释清楚,让评审者在不立刻跳进源码的前提下,也能对正确性、吞吐和资源边界形成稳定判断。
过滤流水线
过滤路径被刻意设计成“聚焦且可组合”的执行链。当前 baseline 支持:
- predicate:最小平均质量、最小长度、最大长度、最大
N比例; - mutator:质量修剪、adapter trimming、polyG trimming、受控的 polyX trimming;
- 单次遍历执行:让过滤与修剪在同一条处理链内完成,而不是为每一步反复重建输入流。
因此,过滤层的重点不是“罗列所有可能的预处理变换”,而是在保持记录合法性、序列/质量长度一致,以及吞吐可控的前提下,完成一条窄而清晰的 QC 处理路径。命令参数层面的细节请继续看 CLI 参考,阶段边界为什么这样划分则回到 架构。
统计路径
统计路径的存在,是为了让 QC 决策保持可解释。stat 命令负责输出 summary metrics 与逐位点测量结果,而不只是一个“成功/失败”的终端状态。按照当前维护中的范围,这包括读段数量、长度分布、碱基组成、GC 含量,以及类似 Q20/Q30 的质量指标。
产品 baseline 还允许在默认文本报告之外输出轻量级 signature sidecar。需要强调的是:sidecar 只能作为附加材料,不能替代主报告契约。这一点也正是研究附录在比较报告型工具时会反复提到的边界。
执行模型
FastQTools 沿用架构层描述的同一套阶段模型:source → processing → sink。这背后的执行承诺可以概括为:
- reader 负责读取与批次形成;
- processing 阶段负责适合并发的过滤、修剪与统计工作;
- sink 负责有序输出、汇总写回与最终错误边界。
当前维护中的并发实现基于 oneTBB parallel_pipeline,但对读者来说,更关键的并不是“用了哪个库”,而是执行路径始终保持分阶段、可审查、且资源有界。于是,性能证据与实现行为可以沿着同一套模型被解释,而不会出现“快的时候一套说法、正确的时候另一套说法”。
内存约束
内存策略之所以属于算法层,是因为吞吐故事本身就依赖它。FastqBatch 为记录数据提供连续存储,记录字段则在批次生命周期内以 std::string_view 视图暴露出来。这样可以减少无谓复制,但也带来一条硬约束:视图绝不能逃逸出所属批次的生命周期。
正确性不变量
算法层应该用不变量来评审,而不能只看吞吐:
| 不变量 | 为什么重要 |
|---|---|
| FASTQ 记录保持四行逻辑单元。 | 如果记录结构变得含混,解析再快也没有意义。 |
| mutation 后 sequence 与 quality 长度仍然一致。 | 过滤与修剪不能产出无效 FASTQ。 |
| 同一输入与配置下 predicate 决策保持确定性。 | 可复现 QC 比机会性的并行顺序更重要。 |
| 批次视图不能逃逸出所属存储。 | 零拷贝只有在生命周期纪律明确时才安全。 |
| signature sidecar 只能作为附加输出。 | 可选 QC 摘要不能替代默认 stat 报告契约。 |