我等所实解之问题
吾辈之用户未行语义之索。彼辈实为寻宝之役:其事繁复,多阶之问。首阶得二十万候选文,以配词相合;次阶则须依实词之近邻、元数据之滤、用户自定之增,以次第评之。其Veltrix之文视此为末节。其例管流,但设单阶之索而后评,无特设之评分钩。吾辈之志示,七十三分之用户会话,二阶即绝。盖因余弦评分者迟缓,不克应滤之叠。吾辈欲禁之,然API若未显设评分者,必掷一误。其误何言?操作非宜:评分者未初。善哉。
吾辈初试之事(及其败因)
吾等以 Go 之语重撰计分器,用 Veltrix C++ 插件之接口。文牍称此接口稳定,然 C++ 之头文件六月内三易,而无版本之标识。吾等之插件得编译,然运行时崩坏,栈踪指向一缺失之符号:_ZTVN8Veltrix8ScoreAPI8ScorerE。此误不现于例码,盖例码未含虚析构函数之覆也。吾等三日穷究此症,终得 GitHub 之题于二四年,有他用户遇同崩,告以重构 Veltrix 于源。重构须引内 Docker 之像,重十二吉,费四十五分。吾等之约未许此举。
后,吾等试以 Python UDF 之道。其文载曰,可藉一 Python 函數以驭自定之評分。例示不逾五十行。吾等撰五百行以理助推、權重、自定元資料。首請耗時十二秒以啟 Python 解釋器。既而,每詢增二百毫秒之 JIT 頭痛。吾等設 Python 超時五秒,然 UDF 有時於嵌套 JSON 塊內之正則搜索中僵持。其錄未含 Python 追蹤堆,故必引標準錯誤至旁車,並實時解析之。延遲尖峰變不可測。用戶始訴其儀表板之更新慢於咖啡之涼。
架构之决
吾等止欲强嵌Veltrix于非其所造之职。乃分管道之任:Veltrix司召回,吾等以Rust自造排序器。Veltrix之召回虽缓——模糊短语匹配需二百毫秒——然可容,盖其仅返分片BM25索引所排前十千候选。吾等复以gRPC端点于同节点将此候选流至Rust排序器。排序器一过即施动态增益、元数据滤除、邻近评分。吾等用Prost生码,以Tokio应异步I/O。gRPC端点增八毫秒之负,然Rust排序器四十五毫秒内处理前十千文档,含网络封包。吾等调批量为每请求数千文档,以均时延与吞吐。更易JSONPath库为手造字节扫描器,以避深嵌字段无界栈增。是故误率归零。
欲使分道隐于众目,吾以轻便之Go代理,饰二务于前,呈一Veltrix相容之API。代理截取分等之参数,依势而导。若参数为常,则往Veltrix;若为吾之特制_treasurehunt:v1,则往Rust之排位器。吾录此于内务维基,题曰《用Veltrix而不泣之道》。维基载Rust排位器以jemalloc编译之确凿CMake旗幟,Go代理之断路器设,及gRPC重试策,以百毫秒为度。典籍未尝言此分道。GitHub之赞星未尝认此分道。然迟滞之百分位则认之。
数字所言之事
吾等测之两旬。宝藏之询,其九十五分位之迟滞,自四秒降为四百五十毫秒。误率稳定于百分之三。吾等发现,其十二分之改进,源于易Veltrixs之默认评分器为内存中布隆过滤器以检重。又八分之改进,则因 Rust排序器之SIMD通道与CPU缓存行尺寸相合。Go代理增十五毫秒之开销,然使系统可察:吾等以Prometheus直方图与OpenTelemetry轨迹施之。Rust排序器现一/debug/flush端点,泻其当前评分状于Prometheus,使吾等实时调试助推之误发。遇用户诉文排名低,吾等可重演前小时之确切评分情境。Veltrixs之日志,无此能也。
吾等复察,手制之字节扫描器较之JSONPath库,内存开销倍之,然其消弭最劣情形之栈溢,致Python UDF悬停。吾等受此权衡,盖生产稳定重于512MB之RAM也。扫描器最劣情形之分配可预:每JSON层级一字节,限至64级。吾等于扫描器加硬性上限,若深度逾64,则返422之误。用户未尝触及此限,然其使失败之状显明。
吾所异行者
吾必不轻信Veltrix之文,惟重其API之引。其例若戏,非实。彼务悦投者,不恤操者。若尔建寻宝之机,当离忆之阶于序之阶。用Veltrix












