ANN 查询服务如何用 loadtest 工具跑随机 embedding 的固定 QPS 在线压测?
【免费下载链接】the-algorithmSource code for the X Recommendation Algorithm项目地址: https://gitcode.com/GitHub_Trending/th/the-algorithm
在 the-algorithm 仓库的ann模块中,有一个专门的 loadtest 工具,可以对部署好的 ANN 查询服务做在线压测。本文的场景是:你不想先准备一份真实的 query embedding 数据集,而是让 loadtest 工具自动生成随机 embedding 作为查询,然后以固定的目标 QPS 持续打向一个远端 ANN 查询服务(loadtest_type=remote),测量它在指定时长内各运行时参数下的延迟和吞吐表现。
完整示例来自 ann loadtest README,压测入口实现在 AnnLoadTestMain,随机查询生成逻辑在 LoadTestUtils。
前提条件
- 有一个已在运行的远端 ANN 查询服务,并且知道它的 wily 地址(README 中
service_destination绑定项对应的就是 "wily address of remote query service")。 - 压测通过
aurora job create提交到集群smf1,使用的是 README 给出的ann/src/main/aurora/loadtest/loadtest.aurora配置,示例命令中的smf1集群名与 aurora 配置文件路径按 README 原文保留。 - 压测二进制使用 packer 中已有的
live版本 loadtest binary,无需自己构建;AnnLoadTestMain 源码注释中给出了自行构建上传的方式(./bazel bundle ann/src/main/scala/com/twitter/ann/service/loadtest:bin --bundle-jvm-archive=zip后packer add_version),仅在你需要改动 loadtest 代码时参考。 - 随机查询模式下不需要 HDFS 上的
query_set目录,也不需要 truth set,查询全部由工具在启动时生成。
创建 aurora 压测任务
按 README 的随机 embedding 示例,用如下命令创建压测 job。命令中<role>是占位符,需要替换为你自己的 role 名;service_destination的示例值指向 README 作者的测试服务,必须替换成你自己 ANN 查询服务的 wily 地址,其余绑定值可按需调整:
$ aurora job create smf1/<role>/staging/ann-loadtest-service ann/src/main/aurora/loadtest/loadtest.aurora \ --bind=profile.name=ann-loadtest-service \ --bind=profile.role=<role> \ --bind=profile.duration_sec=10 \ --bind=profile.number_of_neighbors=10 \ --bind=profile.qps=200 \ --bind=profile.algo=hnsw \ --bind=profile.metric=Cosine \ --bind=profile.index_id_type=int \ --bind=profile.hnsw_ef=400,600,800 \ --bind=profile.embedding_dimension=3 \ --bind=profile.concurrency_level=8 \ --bind=profile.loadtest_type=remote \ --bind=profile.service_destination=/srv#/staging/local/apoorvs/ann-server-test \ --bind=profile.with_random_queries=True \ --bind=profile.random_queries_count=50000 \ --bind=profile.random_embedding_min_value=-10.0 \ --bind=profile.random_embedding_max_value=10.0关键参数说明
这些绑定项最终都会映射到 AnnLoadTestMain 中定义的 flag,按下表对照修改:
| 绑定项 | 示例值 | 说明 |
|---|---|---|
qps | 200 | 目标 QPS,即压测每秒向服务发出的查询数 |
duration_sec | 10 | 每一组运行时参数压测持续的时间(秒) |
number_of_neighbors | 10 | 每次查询取回的邻居数,必填,未设置会断言失败 |
algo | hnsw | 被测索引算法,代码中支持annoy、hnsw、faiss |
hnsw_ef | 400,600,800 | HNSW 查询参数 ef,传列表会对每组值各跑一轮压测(即网格搜索);选hnsw时必传 |
metric | Cosine | 距离度量,支持Cosine/L2/InnerProduct |
index_id_type | int | 索引 id 类型,支持string/int/long及实体类型(user/tweet/word/url等,见 README FAQ 对 EntityKind 的说明) |
embedding_dimension | 3 | embedding 维度,必须与被测服务索引的维度一致,且大于 0 |
concurrency_level | 8 | 同一时刻对服务的最大并发请求数,默认 8 |
loadtest_type | remote | remote表示打压远端服务;local是在内存中构建索引做基准测试,不在本文场景内 |
service_destination | /srv#/staging/local/apoorvs/ann-server-test | 远端 ANN 查询服务的 wily 地址,remote模式下必填 |
with_random_queries | True | 开启随机 embedding 查询 |
random_queries_count | 50000 | 生成的随机查询总数,默认 50000 |
random_embedding_min_value/random_embedding_max_value | -10.0/10.0 | 每个随机 embedding 分量的取值上下界;不传时默认-1.0和1.0 |
工具会在启动时按embedding_dimension和random_queries_count生成查询,每个分量的值均匀落在 min/max 之间(上下界相等的配置会被断言拒绝)。这些查询在压测期间被循环复用:worker 按index % queries.size轮转取查询(见 AnnLoadTestWorker 的runWithQps)。
如何定 qps 与 concurrency_level
QPS 和并发是两个相互制约的旋钮,源码注释明确指出了这一点:
- 如果
concurrency_level设得不够高,可能达不到qps设定的目标 QPS; - 反过来,如果
qps设得不够高,也可能达不到concurrency_level设定的并发数。
也就是说,两者要按被测服务的预期延迟配套设置,单调其中一个参数不保证另一个指标生效。qps是压测的上限速率,worker 通过AsyncMeter.perSecond(qps, concurrencyLevel)限流发压。
查看压测结果
README 说明:Load test results will be printed to stdout of an aurora job。任务结束后,AnnLoadTestMain 会向 stdout 依次打印:
- 三行运行参数汇总:
Target QPS: <qps>、Duration per test: <duration_sec>、Concurrency Level: <concurrency_level>; Build results段,表头为indexingTimeSecs toQueryableTimeMs indexSize;Query results段,表头为:
params numNeighbors recall@1 recall@10 recall avgLatencyMicros p50LatencyMicros p90LatencyMicros p99LatencyMicros avgRPS每一行对应一组运行时参数(例如示例中hnsw_ef的400,600,800会各产出一行),便于横向比较不同 ef 下的延迟与 RPS。
注意边界:随机查询模式下工具断言truth_set_dir必须为空,即随机查询和 truth set 不能同时使用——随机 embedding 没有真实最近邻,因此 recall 相关列在本文场景中不用于评估召回质量;要看 recall 需要走 query_set + truth_set 的基准测试路径,那是 README 中另外两个独立场景,不在本文范围内。
可选分支:对 faiss 参数做网格搜索
如果远端服务用 faiss 算法,README 给出了一组额外的参数绑定示例(在随机查询命令的基础上替换algo相关项):
--bind=profile.algo=faiss \ --bind=profile.faiss_nprobe=1,3,9,27,81,128,256,512 \ --bind=profile.faiss_quantizerKfactorRF=1,2 \ --bind=profile.faiss_quantizerNprobe=128 \这些列表型参数同样会各跑一轮,用于网格搜索。README 列出的 faiss 可绑定参数全集为faiss_nprobe、faiss_quantizerEf、faiss_quantizerKfactorRF、faiss_quantizerNprobe、faiss_ht(默认值见 README 代码块)。
限制与排查
按 AnnLoadTestMain 中的断言逻辑,以下配置会直接让任务启动失败,可在报错信息中对照检查:
number_of_neighbors未设置或为空:number_of_neighbors not defined;embedding_dimension小于等于 0:Invalid dimension;algo=hnsw但未传hnsw_ef:Must specify ef;algo=annoy但未传annoy_num_of_nodes_to_explore:Must specify the num_of_nodes_to_explore;loadtest_type=remote但未传service_destination:Service destination not defined;with_random_queries=True时同时给了 truth set 目录:Cannot use truth set when query with random embeddings enabled。
压测过程中单条查询失败会记录为Failed query for $query: <异常>的 error 日志,汇总结果仍会打印到 stdout。
【免费下载链接】the-algorithmSource code for the X Recommendation Algorithm项目地址: https://gitcode.com/GitHub_Trending/th/the-algorithm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考