vectordb-bench 0.0.15__tar.gz → 0.0.17__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/PKG-INFO +1 -1
  2. vectordb_bench-0.0.17/tests/test_rate_runner.py +88 -0
  3. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/__init__.py +1 -1
  4. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/milvus/milvus.py +3 -2
  5. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvector/cli.py +6 -2
  6. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvector/config.py +6 -0
  7. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/dataset.py +8 -5
  8. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/runner/mp_runner.py +94 -4
  9. vectordb_bench-0.0.17/vectordb_bench/backend/runner/rate_runner.py +79 -0
  10. vectordb_bench-0.0.17/vectordb_bench/backend/runner/read_write_runner.py +112 -0
  11. vectordb_bench-0.0.17/vectordb_bench/backend/runner/util.py +32 -0
  12. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/task_runner.py +5 -5
  13. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/cli/cli.py +2 -2
  14. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/concurrent/charts.py +25 -9
  15. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/concurrent.py +5 -1
  16. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/metric.py +1 -0
  17. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/getLeaderboardData.py +3 -0
  18. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/leaderboard.json +1 -1
  19. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/PKG-INFO +1 -1
  20. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/SOURCES.txt +4 -0
  21. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/.devcontainer/Dockerfile +0 -0
  22. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/.devcontainer/devcontainer.json +0 -0
  23. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/.env.example +0 -0
  24. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/.github/workflows/publish_package_on_release.yml +0 -0
  25. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/.github/workflows/pull_request.yml +0 -0
  26. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/.gitignore +0 -0
  27. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/.ruff.toml +0 -0
  28. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/Dockerfile +0 -0
  29. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/LICENSE +0 -0
  30. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/Makefile +0 -0
  31. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/OWNERS +0 -0
  32. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/README.md +0 -0
  33. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/fig/custom_case_run_test.png +0 -0
  34. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/fig/custom_dataset.png +0 -0
  35. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/install/requirements_py3.11.txt +0 -0
  36. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/install.py +0 -0
  37. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/pyproject.toml +0 -0
  38. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/setup.cfg +0 -0
  39. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/conftest.py +0 -0
  40. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/pytest.ini +0 -0
  41. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_bench_runner.py +0 -0
  42. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_chroma.py +0 -0
  43. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_data_source.py +0 -0
  44. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_dataset.py +0 -0
  45. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_elasticsearch_cloud.py +0 -0
  46. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_models.py +0 -0
  47. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_redis.py +0 -0
  48. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/test_utils.py +0 -0
  49. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/tests/ut_cases.py +0 -0
  50. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/__main__.py +0 -0
  51. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/__init__.py +0 -0
  52. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/assembler.py +0 -0
  53. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/cases.py +0 -0
  54. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/__init__.py +0 -0
  55. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/api.py +0 -0
  56. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/aws_opensearch.py +0 -0
  57. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/cli.py +0 -0
  58. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/config.py +0 -0
  59. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/run.py +0 -0
  60. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/chroma/chroma.py +0 -0
  61. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/chroma/config.py +0 -0
  62. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/elastic_cloud/config.py +0 -0
  63. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/elastic_cloud/elastic_cloud.py +0 -0
  64. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/memorydb/cli.py +0 -0
  65. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/memorydb/config.py +0 -0
  66. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/memorydb/memorydb.py +0 -0
  67. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/milvus/cli.py +0 -0
  68. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/milvus/config.py +0 -0
  69. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgdiskann/cli.py +0 -0
  70. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgdiskann/config.py +0 -0
  71. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgdiskann/pgdiskann.py +0 -0
  72. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvecto_rs/cli.py +0 -0
  73. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvecto_rs/config.py +0 -0
  74. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvecto_rs/pgvecto_rs.py +0 -0
  75. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvector/pgvector.py +0 -0
  76. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvectorscale/cli.py +0 -0
  77. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvectorscale/config.py +0 -0
  78. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvectorscale/pgvectorscale.py +0 -0
  79. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pinecone/config.py +0 -0
  80. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pinecone/pinecone.py +0 -0
  81. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/qdrant_cloud/config.py +0 -0
  82. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/qdrant_cloud/qdrant_cloud.py +0 -0
  83. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/redis/cli.py +0 -0
  84. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/redis/config.py +0 -0
  85. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/redis/redis.py +0 -0
  86. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/test/cli.py +0 -0
  87. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/test/config.py +0 -0
  88. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/test/test.py +0 -0
  89. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/weaviate_cloud/cli.py +0 -0
  90. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/weaviate_cloud/config.py +0 -0
  91. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/weaviate_cloud/weaviate_cloud.py +0 -0
  92. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/zilliz_cloud/cli.py +0 -0
  93. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/zilliz_cloud/config.py +0 -0
  94. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/zilliz_cloud/zilliz_cloud.py +0 -0
  95. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/data_source.py +0 -0
  96. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/result_collector.py +0 -0
  97. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/runner/__init__.py +0 -0
  98. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/runner/serial_runner.py +0 -0
  99. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/backend/utils.py +0 -0
  100. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/base.py +0 -0
  101. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/cli/__init__.py +0 -0
  102. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/cli/vectordbbench.py +0 -0
  103. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/config-files/sample_config.yml +0 -0
  104. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/custom/custom_case.json +0 -0
  105. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/charts.py +0 -0
  106. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/data.py +0 -0
  107. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/expanderStyle.py +0 -0
  108. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/filters.py +0 -0
  109. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/footer.py +0 -0
  110. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/headerIcon.py +0 -0
  111. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/nav.py +0 -0
  112. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/priceTable.py +0 -0
  113. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/stPageConfig.py +0 -0
  114. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/displayCustomCase.py +0 -0
  115. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/displaypPrams.py +0 -0
  116. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/getCustomConfig.py +0 -0
  117. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/initStyle.py +0 -0
  118. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/get_results/saveAsImage.py +0 -0
  119. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/autoRefresh.py +0 -0
  120. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/caseSelector.py +0 -0
  121. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/dbConfigSetting.py +0 -0
  122. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/dbSelector.py +0 -0
  123. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/generateTasks.py +0 -0
  124. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/hideSidebar.py +0 -0
  125. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/initStyle.py +0 -0
  126. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/submitTask.py +0 -0
  127. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/tables/data.py +0 -0
  128. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/config/dbCaseConfigs.py +0 -0
  129. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/config/dbPrices.py +0 -0
  130. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/config/styles.py +0 -0
  131. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/custom.py +0 -0
  132. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/quries_per_dollar.py +0 -0
  133. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/run_test.py +0 -0
  134. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/tables.py +0 -0
  135. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/utils.py +0 -0
  136. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/frontend/vdb_benchmark.py +0 -0
  137. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/interface.py +0 -0
  138. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/log_util.py +0 -0
  139. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/models.py +0 -0
  140. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/ElasticCloud/result_20230727_standard_elasticcloud.json +0 -0
  141. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/ElasticCloud/result_20230808_standard_elasticcloud.json +0 -0
  142. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/Milvus/result_20230727_standard_milvus.json +0 -0
  143. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/Milvus/result_20230808_standard_milvus.json +0 -0
  144. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/PgVector/result_20230727_standard_pgvector.json +0 -0
  145. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/PgVector/result_20230808_standard_pgvector.json +0 -0
  146. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/Pinecone/result_20230727_standard_pinecone.json +0 -0
  147. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/Pinecone/result_20230808_standard_pinecone.json +0 -0
  148. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/QdrantCloud/result_20230727_standard_qdrantcloud.json +0 -0
  149. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/QdrantCloud/result_20230808_standard_qdrantcloud.json +0 -0
  150. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/WeaviateCloud/result_20230727_standard_weaviatecloud.json +0 -0
  151. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/WeaviateCloud/result_20230808_standard_weaviatecloud.json +0 -0
  152. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/ZillizCloud/result_20230727_standard_zillizcloud.json +0 -0
  153. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/ZillizCloud/result_20230808_standard_zillizcloud.json +0 -0
  154. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/ZillizCloud/result_20240105_standard_202401_zillizcloud.json +0 -0
  155. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench/results/dbPrices.json +0 -0
  156. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/dependency_links.txt +0 -0
  157. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/entry_points.txt +0 -0
  158. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/requires.txt +0 -0
  159. {vectordb_bench-0.0.15 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vectordb-bench
3
- Version: 0.0.15
3
+ Version: 0.0.17
4
4
  Summary: VectorDBBench is not just an offering of benchmark results for mainstream vector databases and cloud services, it's your go-to tool for the ultimate performance and cost-effectiveness comparison. Designed with ease-of-use in mind, VectorDBBench is devised to help users, even non-professionals, reproduce results or test new systems, making the hunt for the optimal choice amongst a plethora of cloud services and open-source vector databases a breeze.
5
5
  Author-email: XuanYang-cn <xuan.yang@zilliz.com>
6
6
  Project-URL: repository, https://github.com/zilliztech/VectorDBBench
@@ -0,0 +1,88 @@
1
+ from typing import Iterable
2
+ import argparse
3
+ from vectordb_bench.backend.dataset import Dataset, DatasetSource
4
+ from vectordb_bench.backend.runner.rate_runner import RatedMultiThreadingInsertRunner
5
+ from vectordb_bench.backend.runner.read_write_runner import ReadWriteRunner
6
+ from vectordb_bench.backend.clients import DB, VectorDB
7
+ from vectordb_bench.backend.clients.milvus.config import FLATConfig
8
+ from vectordb_bench.backend.clients.zilliz_cloud.config import AutoIndexConfig
9
+
10
+ import logging
11
+
12
+ log = logging.getLogger("vectordb_bench")
13
+ log.setLevel(logging.DEBUG)
14
+
15
+ def get_rate_runner(db):
16
+ cohere = Dataset.COHERE.manager(100_000)
17
+ prepared = cohere.prepare(DatasetSource.AliyunOSS)
18
+ assert prepared
19
+ runner = RatedMultiThreadingInsertRunner(
20
+ rate = 10,
21
+ db = db,
22
+ dataset = cohere,
23
+ )
24
+
25
+ return runner
26
+
27
+ def test_rate_runner(db, insert_rate):
28
+ runner = get_rate_runner(db)
29
+
30
+ _, t = runner.run_with_rate()
31
+ log.info(f"insert run done, time={t}")
32
+
33
+ def test_read_write_runner(db, insert_rate, conc: list, search_stage: Iterable[float], read_dur_after_write: int, local: bool=False):
34
+ cohere = Dataset.COHERE.manager(1_000_000)
35
+ if local is True:
36
+ source = DatasetSource.AliyunOSS
37
+ else:
38
+ source = DatasetSource.S3
39
+ prepared = cohere.prepare(source)
40
+ assert prepared
41
+
42
+ rw_runner = ReadWriteRunner(
43
+ db=db,
44
+ dataset=cohere,
45
+ insert_rate=insert_rate,
46
+ search_stage=search_stage,
47
+ read_dur_after_write=read_dur_after_write,
48
+ concurrencies=conc
49
+ )
50
+ rw_runner.run_read_write()
51
+
52
+
53
+ def get_db(db: str, config: dict) -> VectorDB:
54
+ if db == DB.Milvus.name:
55
+ return DB.Milvus.init_cls(dim=768, db_config=config, db_case_config=FLATConfig(metric_type="COSINE"), drop_old=True, pre_load=True)
56
+ elif db == DB.ZillizCloud.name:
57
+ return DB.ZillizCloud.init_cls(dim=768, db_config=config, db_case_config=AutoIndexConfig(metric_type="COSINE"), drop_old=True, pre_load=True)
58
+ else:
59
+ raise ValueError(f"unknown db: {db}")
60
+
61
+
62
+ if __name__ == "__main__":
63
+ parser = argparse.ArgumentParser()
64
+ parser.add_argument("-r", "--insert_rate", type=int, default="1000", help="insert entity row count per seconds, cps")
65
+ parser.add_argument("-d", "--db", type=str, default=DB.Milvus.name, help="db name")
66
+ parser.add_argument("-t", "--duration", type=int, default=300, help="stage search duration in seconds")
67
+ parser.add_argument("--use_s3", action='store_true', help="whether to use S3 dataset")
68
+
69
+ flags = parser.parse_args()
70
+
71
+ # TODO read uri, user, password from .env
72
+ config = {
73
+ "uri": "http://localhost:19530",
74
+ "user": "",
75
+ "password": "",
76
+ }
77
+
78
+ conc = (1, 15, 50)
79
+ search_stage = (0.5, 0.6, 0.7, 0.8, 0.9, 1.0)
80
+
81
+ db = get_db(flags.db, config)
82
+ test_read_write_runner(
83
+ db=db,
84
+ insert_rate=flags.insert_rate,
85
+ conc=conc,
86
+ search_stage=search_stage,
87
+ read_dur_after_write=flags.duration,
88
+ local=flags.use_s3)
@@ -17,7 +17,7 @@ class config:
17
17
 
18
18
  DEFAULT_DATASET_URL = env.str("DEFAULT_DATASET_URL", AWS_S3_URL)
19
19
  DATASET_LOCAL_DIR = env.path("DATASET_LOCAL_DIR", "/tmp/vectordb_bench/dataset")
20
- NUM_PER_BATCH = env.int("NUM_PER_BATCH", 5000)
20
+ NUM_PER_BATCH = env.int("NUM_PER_BATCH", 100)
21
21
 
22
22
  DROP_OLD = env.bool("DROP_OLD", True)
23
23
  USE_SHUFFLED_DATA = env.bool("USE_SHUFFLED_DATA", True)
@@ -66,7 +66,8 @@ class Milvus(VectorDB):
66
66
  self.case_config.index_param(),
67
67
  index_name=self._index_name,
68
68
  )
69
- # self._pre_load(coll)
69
+ if kwargs.get("pre_load") is True:
70
+ self._pre_load(col)
70
71
 
71
72
  connections.disconnect("default")
72
73
 
@@ -92,7 +93,7 @@ class Milvus(VectorDB):
92
93
  self._post_insert()
93
94
  log.info(f"{self.name} optimizing before search")
94
95
  try:
95
- self.col.load()
96
+ self.col.load(refresh=True)
96
97
  except Exception as e:
97
98
  log.warning(f"{self.name} optimize error: {e}")
98
99
  raise e from None
@@ -18,11 +18,12 @@ from ....cli.cli import (
18
18
  from vectordb_bench.backend.clients import DB
19
19
 
20
20
 
21
-
22
21
  def set_default_quantized_fetch_limit(ctx, param, value):
23
22
  if ctx.params.get("reranking") and value is None:
24
23
  # ef_search is the default value for quantized_fetch_limit as it's bound by ef_search.
25
- return ctx.params["ef_search"]
24
+ # 100 is default value for quantized_fetch_limit for IVFFlat.
25
+ default_value = ctx.params["ef_search"] if ctx.command.name == "pgvectorhnsw" else 100
26
+ return default_value
26
27
  return value
27
28
 
28
29
  class PgVectorTypedDict(CommonTypedDict):
@@ -136,6 +137,9 @@ def PgVectorIVFFlat(
136
137
  lists=parameters["lists"],
137
138
  probes=parameters["probes"],
138
139
  quantization_type=parameters["quantization_type"],
140
+ reranking=parameters["reranking"],
141
+ reranking_metric=parameters["reranking_metric"],
142
+ quantized_fetch_limit=parameters["quantized_fetch_limit"],
139
143
  ),
140
144
  **parameters,
141
145
  )
@@ -168,6 +168,9 @@ class PgVectorIVFFlatConfig(PgVectorIndexConfig):
168
168
  maintenance_work_mem: Optional[str] = None
169
169
  max_parallel_workers: Optional[int] = None
170
170
  quantization_type: Optional[str] = None
171
+ reranking: Optional[bool] = None
172
+ quantized_fetch_limit: Optional[int] = None
173
+ reranking_metric: Optional[str] = None
171
174
 
172
175
  def index_param(self) -> PgVectorIndexParam:
173
176
  index_parameters = {"lists": self.lists}
@@ -187,6 +190,9 @@ class PgVectorIVFFlatConfig(PgVectorIndexConfig):
187
190
  def search_param(self) -> PgVectorSearchParam:
188
191
  return {
189
192
  "metric_fun_op": self.parse_metric_fun_op(),
193
+ "reranking": self.reranking,
194
+ "reranking_metric_fun_op": self.parse_reranking_metric_fun_op(),
195
+ "quantized_fetch_limit": self.quantized_fetch_limit,
190
196
  }
191
197
 
192
198
  def session_param(self) -> PgVectorSessionCommands:
@@ -57,11 +57,11 @@ class CustomDataset(BaseDataset):
57
57
  dir: str
58
58
  file_num: int
59
59
  isCustom: bool = True
60
-
60
+
61
61
  @validator("size")
62
62
  def verify_size(cls, v):
63
63
  return v
64
-
64
+
65
65
  @property
66
66
  def label(self) -> str:
67
67
  return "Custom"
@@ -73,7 +73,8 @@ class CustomDataset(BaseDataset):
73
73
  @property
74
74
  def file_count(self) -> int:
75
75
  return self.file_num
76
-
76
+
77
+
77
78
  class LAION(BaseDataset):
78
79
  name: str = "LAION"
79
80
  dim: int = 768
@@ -242,13 +243,15 @@ class DataSetIterator:
242
243
  self._cur = None
243
244
  self._sub_idx = [0 for i in range(len(self._ds.train_files))] # iter num for each file
244
245
 
246
+ def __iter__(self):
247
+ return self
248
+
245
249
  def _get_iter(self, file_name: str):
246
250
  p = pathlib.Path(self._ds.data_dir, file_name)
247
251
  log.info(f"Get iterator for {p.name}")
248
252
  if not p.exists():
249
253
  raise IndexError(f"No such file {p}")
250
- log.warning(f"No such file: {p}")
251
- return ParquetFile(p).iter_batches(config.NUM_PER_BATCH)
254
+ return ParquetFile(p, memory_map=True, pre_buffer=True).iter_batches(config.NUM_PER_BATCH)
252
255
 
253
256
  def __next__(self) -> pd.DataFrame:
254
257
  """return the data in the next file of the training list"""
@@ -64,7 +64,7 @@ class MultiProcessingSearchRunner:
64
64
  log.warning(f"VectorDB search_embedding error: {e}")
65
65
  traceback.print_exc(chain=True)
66
66
  raise e from None
67
-
67
+
68
68
  latencies.append(time.perf_counter() - s)
69
69
  count += 1
70
70
  # loop through the test data
@@ -87,11 +87,14 @@ class MultiProcessingSearchRunner:
87
87
  log.debug(f"MultiProcessingSearchRunner get multiprocessing start method: {mp_start_method}")
88
88
  return mp.get_context(mp_start_method)
89
89
 
90
- def _run_all_concurrencies_mem_efficient(self) -> float:
90
+
91
+
92
+ def _run_all_concurrencies_mem_efficient(self):
91
93
  max_qps = 0
92
94
  conc_num_list = []
93
95
  conc_qps_list = []
94
96
  conc_latency_p99_list = []
97
+ conc_latency_avg_list = []
95
98
  try:
96
99
  for conc in self.concurrencies:
97
100
  with mp.Manager() as m:
@@ -111,13 +114,15 @@ class MultiProcessingSearchRunner:
111
114
  start = time.perf_counter()
112
115
  all_count = sum([r.result()[0] for r in future_iter])
113
116
  latencies = sum([r.result()[2] for r in future_iter], start=[])
114
- latency_p99 = np.percentile(latencies, 0.99)
117
+ latency_p99 = np.percentile(latencies, 99)
118
+ latency_avg = np.mean(latencies)
115
119
  cost = time.perf_counter() - start
116
120
 
117
121
  qps = round(all_count / cost, 4)
118
122
  conc_num_list.append(conc)
119
123
  conc_qps_list.append(qps)
120
124
  conc_latency_p99_list.append(latency_p99)
125
+ conc_latency_avg_list.append(latency_avg)
121
126
  log.info(f"End search in concurrency {conc}: dur={cost}s, total_count={all_count}, qps={qps}")
122
127
 
123
128
  if qps > max_qps:
@@ -134,7 +139,7 @@ class MultiProcessingSearchRunner:
134
139
  finally:
135
140
  self.stop()
136
141
 
137
- return max_qps, conc_num_list, conc_qps_list, conc_latency_p99_list
142
+ return max_qps, conc_num_list, conc_qps_list, conc_latency_p99_list, conc_latency_avg_list
138
143
 
139
144
  def run(self) -> float:
140
145
  """
@@ -145,3 +150,88 @@ class MultiProcessingSearchRunner:
145
150
 
146
151
  def stop(self) -> None:
147
152
  pass
153
+
154
+ def run_by_dur(self, duration: int) -> float:
155
+ return self._run_by_dur(duration)
156
+
157
+ def _run_by_dur(self, duration: int) -> float:
158
+ max_qps = 0
159
+ try:
160
+ for conc in self.concurrencies:
161
+ with mp.Manager() as m:
162
+ q, cond = m.Queue(), m.Condition()
163
+ with concurrent.futures.ProcessPoolExecutor(mp_context=self.get_mp_context(), max_workers=conc) as executor:
164
+ log.info(f"Start search_by_dur {duration}s in concurrency {conc}, filters: {self.filters}")
165
+ future_iter = [executor.submit(self.search_by_dur, duration, self.test_data, q, cond) for i in range(conc)]
166
+ # Sync all processes
167
+ while q.qsize() < conc:
168
+ sleep_t = conc if conc < 10 else 10
169
+ time.sleep(sleep_t)
170
+
171
+ with cond:
172
+ cond.notify_all()
173
+ log.info(f"Syncing all process and start concurrency search, concurrency={conc}")
174
+
175
+ start = time.perf_counter()
176
+ all_count = sum([r.result() for r in future_iter])
177
+ cost = time.perf_counter() - start
178
+
179
+ qps = round(all_count / cost, 4)
180
+ log.info(f"End search in concurrency {conc}: dur={cost}s, total_count={all_count}, qps={qps}")
181
+
182
+ if qps > max_qps:
183
+ max_qps = qps
184
+ log.info(f"Update largest qps with concurrency {conc}: current max_qps={max_qps}")
185
+ except Exception as e:
186
+ log.warning(f"Fail to search all concurrencies: {self.concurrencies}, max_qps before failure={max_qps}, reason={e}")
187
+ traceback.print_exc()
188
+
189
+ # No results available, raise exception
190
+ if max_qps == 0.0:
191
+ raise e from None
192
+
193
+ finally:
194
+ self.stop()
195
+
196
+ return max_qps
197
+
198
+
199
+ def search_by_dur(self, dur: int, test_data: list[list[float]], q: mp.Queue, cond: mp.Condition) -> int:
200
+ # sync all process
201
+ q.put(1)
202
+ with cond:
203
+ cond.wait()
204
+
205
+ with self.db.init():
206
+ num, idx = len(test_data), random.randint(0, len(test_data) - 1)
207
+
208
+ start_time = time.perf_counter()
209
+ count = 0
210
+ while time.perf_counter() < start_time + dur:
211
+ s = time.perf_counter()
212
+ try:
213
+ self.db.search_embedding(
214
+ test_data[idx],
215
+ self.k,
216
+ self.filters,
217
+ )
218
+ except Exception as e:
219
+ log.warning(f"VectorDB search_embedding error: {e}")
220
+ traceback.print_exc(chain=True)
221
+ raise e from None
222
+
223
+ count += 1
224
+ # loop through the test data
225
+ idx = idx + 1 if idx < num - 1 else 0
226
+
227
+ if count % 500 == 0:
228
+ log.debug(f"({mp.current_process().name:16}) search_count: {count}, latest_latency={time.perf_counter()-s}")
229
+
230
+ total_dur = round(time.perf_counter() - start_time, 4)
231
+ log.debug(
232
+ f"{mp.current_process().name:16} search {self.duration}s: "
233
+ f"actual_dur={total_dur}s, count={count}, qps in this process: {round(count / total_dur, 4):3}"
234
+ )
235
+
236
+ return count
237
+
@@ -0,0 +1,79 @@
1
+ import logging
2
+ import time
3
+ from concurrent.futures import ThreadPoolExecutor
4
+ import multiprocessing as mp
5
+
6
+
7
+ from vectordb_bench.backend.clients import api
8
+ from vectordb_bench.backend.dataset import DataSetIterator
9
+ from vectordb_bench.backend.utils import time_it
10
+ from vectordb_bench import config
11
+
12
+ from .util import get_data, is_futures_completed, get_future_exceptions
13
+ log = logging.getLogger(__name__)
14
+
15
+
16
+ class RatedMultiThreadingInsertRunner:
17
+ def __init__(
18
+ self,
19
+ rate: int, # numRows per second
20
+ db: api.VectorDB,
21
+ dataset_iter: DataSetIterator,
22
+ normalize: bool = False,
23
+ timeout: float | None = None,
24
+ ):
25
+ self.timeout = timeout if isinstance(timeout, (int, float)) else None
26
+ self.dataset = dataset_iter
27
+ self.db = db
28
+ self.normalize = normalize
29
+ self.insert_rate = rate
30
+ self.batch_rate = rate // config.NUM_PER_BATCH
31
+
32
+ def send_insert_task(self, db, emb: list[list[float]], metadata: list[str]):
33
+ db.insert_embeddings(emb, metadata)
34
+
35
+ @time_it
36
+ def run_with_rate(self, q: mp.Queue):
37
+ with ThreadPoolExecutor(max_workers=mp.cpu_count()) as executor:
38
+ executing_futures = []
39
+
40
+ @time_it
41
+ def submit_by_rate() -> bool:
42
+ rate = self.batch_rate
43
+ for data in self.dataset:
44
+ emb, metadata = get_data(data, self.normalize)
45
+ executing_futures.append(executor.submit(self.send_insert_task, self.db, emb, metadata))
46
+ rate -= 1
47
+
48
+ if rate == 0:
49
+ return False
50
+ return rate == self.batch_rate
51
+
52
+ with self.db.init():
53
+ while True:
54
+ start_time = time.perf_counter()
55
+ finished, elapsed_time = submit_by_rate()
56
+ if finished is True:
57
+ q.put(None, block=True)
58
+ log.info(f"End of dataset, left unfinished={len(executing_futures)}")
59
+ return
60
+
61
+ q.put(True, block=False)
62
+ wait_interval = 1 - elapsed_time if elapsed_time < 1 else 0.001
63
+
64
+ e, completed = is_futures_completed(executing_futures, wait_interval)
65
+ if completed is True:
66
+ ex = get_future_exceptions(executing_futures)
67
+ if ex is not None:
68
+ log.warn(f"task error, terminating, err={ex}")
69
+ q.put(None)
70
+ executor.shutdown(wait=True, cancel_futures=True)
71
+ raise ex
72
+ else:
73
+ log.debug(f"Finished {len(executing_futures)} insert-{config.NUM_PER_BATCH} task in 1s, wait_interval={wait_interval:.2f}")
74
+ executing_futures = []
75
+ else:
76
+ log.warning(f"Failed to finish tasks in 1s, {e}, waited={wait_interval:.2f}, try to check the next round")
77
+ dur = time.perf_counter() - start_time
78
+ if dur < 1:
79
+ time.sleep(1 - dur)
@@ -0,0 +1,112 @@
1
+ import logging
2
+ from typing import Iterable
3
+ import multiprocessing as mp
4
+ import concurrent
5
+ import numpy as np
6
+ import math
7
+
8
+ from .mp_runner import MultiProcessingSearchRunner
9
+ from .serial_runner import SerialSearchRunner
10
+ from .rate_runner import RatedMultiThreadingInsertRunner
11
+ from vectordb_bench.backend.clients import api
12
+ from vectordb_bench.backend.dataset import DatasetManager
13
+
14
+ log = logging.getLogger(__name__)
15
+
16
+
17
+ class ReadWriteRunner(MultiProcessingSearchRunner, RatedMultiThreadingInsertRunner):
18
+ def __init__(
19
+ self,
20
+ db: api.VectorDB,
21
+ dataset: DatasetManager,
22
+ insert_rate: int = 1000,
23
+ normalize: bool = False,
24
+ k: int = 100,
25
+ filters: dict | None = None,
26
+ concurrencies: Iterable[int] = (1, 15, 50),
27
+ search_stage: Iterable[float] = (0.5, 0.6, 0.7, 0.8, 0.9, 1.0), # search in any insert portion, 0.0 means search from the start
28
+ read_dur_after_write: int = 300, # seconds, search duration when insertion is done
29
+ timeout: float | None = None,
30
+ ):
31
+ self.insert_rate = insert_rate
32
+ self.data_volume = dataset.data.size
33
+
34
+ for stage in search_stage:
35
+ assert 0.0 <= stage <= 1.0, "each search stage should be in [0.0, 1.0]"
36
+ self.search_stage = sorted(search_stage)
37
+ self.read_dur_after_write = read_dur_after_write
38
+
39
+ log.info(f"Init runner, concurencys={concurrencies}, search_stage={search_stage}, stage_search_dur={read_dur_after_write}")
40
+
41
+ test_emb = np.stack(dataset.test_data["emb"])
42
+ if normalize:
43
+ test_emb = test_emb / np.linalg.norm(test_emb, axis=1)[:, np.newaxis]
44
+ test_emb = test_emb.tolist()
45
+
46
+ MultiProcessingSearchRunner.__init__(
47
+ self,
48
+ db=db,
49
+ test_data=test_emb,
50
+ k=k,
51
+ filters=filters,
52
+ concurrencies=concurrencies,
53
+ )
54
+ RatedMultiThreadingInsertRunner.__init__(
55
+ self,
56
+ rate=insert_rate,
57
+ db=db,
58
+ dataset_iter=iter(dataset),
59
+ normalize=normalize,
60
+ )
61
+ self.serial_search_runner = SerialSearchRunner(
62
+ db=db,
63
+ test_data=test_emb,
64
+ ground_truth=dataset.gt_data,
65
+ k=k,
66
+ )
67
+
68
+ def run_read_write(self):
69
+ futures = []
70
+ with mp.Manager() as m:
71
+ q = m.Queue()
72
+ with concurrent.futures.ProcessPoolExecutor(mp_context=mp.get_context("spawn"), max_workers=2) as executor:
73
+ futures.append(executor.submit(self.run_with_rate, q))
74
+ futures.append(executor.submit(self.run_search_by_sig, q))
75
+
76
+ for future in concurrent.futures.as_completed(futures):
77
+ res = future.result()
78
+ log.info(f"Result = {res}")
79
+
80
+ log.info("Concurrent read write all done")
81
+
82
+
83
+ def run_search_by_sig(self, q):
84
+ res = []
85
+ total_batch = math.ceil(self.data_volume / self.insert_rate)
86
+ batch = 0
87
+ recall = 'x'
88
+
89
+ for idx, stage in enumerate(self.search_stage):
90
+ target_batch = int(total_batch * stage)
91
+ while q.get(block=True):
92
+ batch += 1
93
+ if batch >= target_batch:
94
+ perc = int(stage * 100)
95
+ log.info(f"Insert {perc}% done, total batch={total_batch}")
96
+ log.info(f"[{batch}/{total_batch}] Serial search - {perc}% start")
97
+ recall, ndcg, p99 =self.serial_search_runner.run()
98
+
99
+ if idx < len(self.search_stage) - 1:
100
+ stage_search_dur = (self.data_volume * (self.search_stage[idx + 1] - stage) // self.insert_rate) // len(self.concurrencies)
101
+ if stage_search_dur < 30:
102
+ log.warning(f"Search duration too short, please reduce concurrency count or insert rate, or increase dataset volume: dur={stage_search_dur}, concurrencies={len(self.concurrencies)}, insert_rate={self.insert_rate}")
103
+ log.info(f"[{batch}/{total_batch}] Conc search - {perc}% start, dur for each conc={stage_search_dur}s")
104
+ else:
105
+ last_search_dur = self.data_volume * (1.0 - stage) // self.insert_rate
106
+ stage_search_dur = last_search_dur + self.read_dur_after_write
107
+ log.info(f"[{batch}/{total_batch}] Last conc search - {perc}% start, [read_until_write|read_after_write|total] =[{last_search_dur}s|{self.read_dur_after_write}s|{stage_search_dur}s]")
108
+
109
+ max_qps = self.run_by_dur(stage_search_dur)
110
+ res.append((perc, max_qps, recall))
111
+ break
112
+ return res
@@ -0,0 +1,32 @@
1
+ import logging
2
+ import concurrent
3
+ from typing import Iterable
4
+
5
+ from pandas import DataFrame
6
+ import numpy as np
7
+
8
+ log = logging.getLogger(__name__)
9
+
10
+ def get_data(data_df: DataFrame, normalize: bool) -> tuple[list[list[float]], list[str]]:
11
+ all_metadata = data_df['id'].tolist()
12
+ emb_np = np.stack(data_df['emb'])
13
+ if normalize:
14
+ log.debug("normalize the 100k train data")
15
+ all_embeddings = (emb_np / np.linalg.norm(emb_np, axis=1)[:, np.newaxis]).tolist()
16
+ else:
17
+ all_embeddings = emb_np.tolist()
18
+ return all_embeddings, all_metadata
19
+
20
+ def is_futures_completed(futures: Iterable[concurrent.futures.Future], interval) -> (Exception, bool):
21
+ try:
22
+ list(concurrent.futures.as_completed(futures, timeout=interval))
23
+ except TimeoutError as e:
24
+ return e, False
25
+ return None, True
26
+
27
+
28
+ def get_future_exceptions(futures: Iterable[concurrent.futures.Future]) -> BaseException | None:
29
+ for f in futures:
30
+ if f.exception() is not None:
31
+ return f.exception()
32
+ return
@@ -150,7 +150,7 @@ class CaseRunner(BaseModel):
150
150
  )
151
151
 
152
152
  self._init_search_runner()
153
-
153
+
154
154
  m.qps, m.conc_num_list, m.conc_qps_list, m.conc_latency_p99_list = self._conc_search()
155
155
  m.recall, m.serial_latency_p99 = self._serial_search()
156
156
  '''
@@ -176,6 +176,9 @@ class CaseRunner(BaseModel):
176
176
  or TaskStage.SEARCH_CONCURRENT in self.config.stages
177
177
  ):
178
178
  self._init_search_runner()
179
+ if TaskStage.SEARCH_CONCURRENT in self.config.stages:
180
+ search_results = self._conc_search()
181
+ m.qps, m.conc_num_list, m.conc_qps_list, m.conc_latency_p99_list, m.conc_latency_avg_list = search_results
179
182
  if TaskStage.SEARCH_SERIAL in self.config.stages:
180
183
  search_results = self._serial_search()
181
184
  '''
@@ -183,10 +186,7 @@ class CaseRunner(BaseModel):
183
186
  m.serial_latencies = search_results.serial_latencies
184
187
  '''
185
188
  m.recall, m.ndcg, m.serial_latency_p99 = search_results
186
- if TaskStage.SEARCH_CONCURRENT in self.config.stages:
187
- search_results = self._conc_search()
188
- m.qps, m.conc_num_list, m.conc_qps_list, m.conc_latency_p99_list = search_results
189
-
189
+
190
190
  except Exception as e:
191
191
  log.warning(f"Failed to run performance case, reason = {e}")
192
192
  traceback.print_exc()
@@ -414,7 +414,7 @@ class HNSWBaseRequiredTypedDict(TypedDict):
414
414
 
415
415
  class HNSWFlavor1(HNSWBaseTypedDict):
416
416
  ef_search: Annotated[
417
- Optional[int], click.option("--ef-search", type=int, help="hnsw ef-search")
417
+ Optional[int], click.option("--ef-search", type=int, help="hnsw ef-search", is_eager=True)
418
418
  ]
419
419
 
420
420
 
@@ -479,7 +479,7 @@ def run(
479
479
  concurrency_duration=parameters["concurrency_duration"],
480
480
  num_concurrency=[int(s) for s in parameters["num_concurrency"]],
481
481
  ),
482
- custom_case=parameters.get("custom_case", {}),
482
+ custom_case=get_custom_case_config(parameters),
483
483
  ),
484
484
  stages=parse_task_stages(
485
485
  (