vectordb-bench 1.0.3__py3-none-any.whl → 1.0.5__py3-none-any.whl

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 (54) hide show
  1. vectordb_bench/backend/cases.py +45 -1
  2. vectordb_bench/backend/clients/__init__.py +32 -0
  3. vectordb_bench/backend/clients/aliyun_opensearch/aliyun_opensearch.py +34 -42
  4. vectordb_bench/backend/clients/aliyun_opensearch/config.py +0 -7
  5. vectordb_bench/backend/clients/milvus/cli.py +216 -0
  6. vectordb_bench/backend/clients/oss_opensearch/cli.py +155 -0
  7. vectordb_bench/backend/clients/oss_opensearch/config.py +157 -0
  8. vectordb_bench/backend/clients/oss_opensearch/oss_opensearch.py +582 -0
  9. vectordb_bench/backend/clients/oss_opensearch/run.py +166 -0
  10. vectordb_bench/backend/clients/s3_vectors/config.py +41 -0
  11. vectordb_bench/backend/clients/s3_vectors/s3_vectors.py +171 -0
  12. vectordb_bench/backend/clients/tidb/cli.py +0 -4
  13. vectordb_bench/backend/clients/tidb/config.py +22 -2
  14. vectordb_bench/backend/dataset.py +70 -0
  15. vectordb_bench/backend/filter.py +17 -0
  16. vectordb_bench/backend/runner/mp_runner.py +4 -0
  17. vectordb_bench/backend/runner/read_write_runner.py +10 -9
  18. vectordb_bench/backend/runner/serial_runner.py +23 -7
  19. vectordb_bench/backend/task_runner.py +5 -4
  20. vectordb_bench/cli/vectordbbench.py +2 -0
  21. vectordb_bench/fig/custom_case_run_test.png +0 -0
  22. vectordb_bench/fig/custom_dataset.png +0 -0
  23. vectordb_bench/fig/homepage/bar-chart.png +0 -0
  24. vectordb_bench/fig/homepage/concurrent.png +0 -0
  25. vectordb_bench/fig/homepage/custom.png +0 -0
  26. vectordb_bench/fig/homepage/label_filter.png +0 -0
  27. vectordb_bench/fig/homepage/qp$.png +0 -0
  28. vectordb_bench/fig/homepage/run_test.png +0 -0
  29. vectordb_bench/fig/homepage/streaming.png +0 -0
  30. vectordb_bench/fig/homepage/table.png +0 -0
  31. vectordb_bench/fig/run_test_select_case.png +0 -0
  32. vectordb_bench/fig/run_test_select_db.png +0 -0
  33. vectordb_bench/fig/run_test_submit.png +0 -0
  34. vectordb_bench/frontend/components/check_results/filters.py +1 -4
  35. vectordb_bench/frontend/components/check_results/nav.py +2 -1
  36. vectordb_bench/frontend/components/concurrent/charts.py +5 -0
  37. vectordb_bench/frontend/components/int_filter/charts.py +60 -0
  38. vectordb_bench/frontend/components/streaming/data.py +7 -0
  39. vectordb_bench/frontend/components/welcome/welcomePrams.py +42 -4
  40. vectordb_bench/frontend/config/dbCaseConfigs.py +60 -13
  41. vectordb_bench/frontend/config/styles.py +3 -0
  42. vectordb_bench/frontend/pages/concurrent.py +1 -1
  43. vectordb_bench/frontend/pages/custom.py +1 -1
  44. vectordb_bench/frontend/pages/int_filter.py +56 -0
  45. vectordb_bench/frontend/pages/streaming.py +16 -3
  46. vectordb_bench/metric.py +7 -0
  47. vectordb_bench/models.py +36 -4
  48. vectordb_bench/results/S3Vectors/result_20250722_standard_s3vectors.json +2509 -0
  49. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/METADATA +1 -3
  50. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/RECORD +54 -32
  51. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/WHEEL +0 -0
  52. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/entry_points.txt +0 -0
  53. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/licenses/LICENSE +0 -0
  54. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/top_level.txt +0 -0
@@ -71,7 +71,6 @@ def main():
71
71
  getResults(resultesContainer, "vectordb_bench_streaming")
72
72
 
73
73
  # # main
74
- # latency_type = st.radio("Latency Type", options=["latency_p99", "latency_avg"])
75
74
  st.markdown("Tests search performance with a **stable** and **fixed** insertion rate.")
76
75
  control_panel = st.columns(3)
77
76
  compared_with_optimized = control_panel[0].toggle(
@@ -84,6 +83,15 @@ def main():
84
83
  value=False,
85
84
  help="Since vdbbench inserts may be faster than vetordb can process them, the time it actually reaches search_stage may have different delays.",
86
85
  )
86
+
87
+ # Latency type selection
88
+ latency_type = control_panel[2].radio(
89
+ "Latency Type",
90
+ options=["latency_p99", "latency_p95"],
91
+ index=0,
92
+ help="Choose between P99 (slowest 1%) or P95 (slowest 5%) latency metrics.",
93
+ )
94
+
87
95
  accuracy_metric = DisplayedMetric.recall
88
96
  show_ndcg = control_panel[1].toggle(
89
97
  "Show **NDCG** instead of Recall.",
@@ -103,6 +111,11 @@ def main():
103
111
  else:
104
112
  if need_adjust:
105
113
  accuracy_metric = DisplayedMetric.adjusted_recall
114
+
115
+ # Determine which latency metric to display
116
+ latency_metric = DisplayedMetric.latency_p99 if latency_type == "latency_p99" else DisplayedMetric.latency_p95
117
+ latency_desc = "serial lantency (p99)" if latency_type == "latency_p99" else "serial lantency (p95)"
118
+
106
119
  line_chart_displayed_y_metrics: list[tuple[DisplayedMetric, str]] = [
107
120
  (
108
121
  DisplayedMetric.qps,
@@ -110,8 +123,8 @@ def main():
110
123
  ),
111
124
  (accuracy_metric, "calculated in each search_stage."),
112
125
  (
113
- DisplayedMetric.latency_p99,
114
- "serial lantency (p99) of **serial search** tests in each search stage.",
126
+ latency_metric,
127
+ f"{latency_desc} of **serial search** tests in each search stage.",
115
128
  ),
116
129
  ]
117
130
  line_chart_displayed_x_metric = DisplayedMetric.search_stage
vectordb_bench/metric.py CHANGED
@@ -21,11 +21,13 @@ class Metric:
21
21
  # for performance cases
22
22
  qps: float = 0.0
23
23
  serial_latency_p99: float = 0.0
24
+ serial_latency_p95: float = 0.0
24
25
  recall: float = 0.0
25
26
  ndcg: float = 0.0
26
27
  conc_num_list: list[int] = field(default_factory=list)
27
28
  conc_qps_list: list[float] = field(default_factory=list)
28
29
  conc_latency_p99_list: list[float] = field(default_factory=list)
30
+ conc_latency_p95_list: list[float] = field(default_factory=list)
29
31
  conc_latency_avg_list: list[float] = field(default_factory=list)
30
32
 
31
33
  # for streaming cases
@@ -36,12 +38,14 @@ class Metric:
36
38
  st_recall_list: list[float] = field(default_factory=list)
37
39
  st_ndcg_list: list[float] = field(default_factory=list)
38
40
  st_serial_latency_p99_list: list[float] = field(default_factory=list)
41
+ st_serial_latency_p95_list: list[float] = field(default_factory=list)
39
42
  st_conc_failed_rate_list: list[float] = field(default_factory=list)
40
43
 
41
44
 
42
45
  QURIES_PER_DOLLAR_METRIC = "QP$ (Quries per Dollar)"
43
46
  LOAD_DURATION_METRIC = "load_duration"
44
47
  SERIAL_LATENCY_P99_METRIC = "serial_latency_p99"
48
+ SERIAL_LATENCY_P95_METRIC = "serial_latency_p95"
45
49
  MAX_LOAD_COUNT_METRIC = "max_load_count"
46
50
  QPS_METRIC = "qps"
47
51
  RECALL_METRIC = "recall"
@@ -49,6 +53,7 @@ RECALL_METRIC = "recall"
49
53
  metric_unit_map = {
50
54
  LOAD_DURATION_METRIC: "s",
51
55
  SERIAL_LATENCY_P99_METRIC: "ms",
56
+ SERIAL_LATENCY_P95_METRIC: "ms",
52
57
  MAX_LOAD_COUNT_METRIC: "K",
53
58
  QURIES_PER_DOLLAR_METRIC: "K",
54
59
  }
@@ -56,6 +61,7 @@ metric_unit_map = {
56
61
  lower_is_better_metrics = [
57
62
  LOAD_DURATION_METRIC,
58
63
  SERIAL_LATENCY_P99_METRIC,
64
+ SERIAL_LATENCY_P95_METRIC,
59
65
  ]
60
66
 
61
67
  metric_order = [
@@ -63,6 +69,7 @@ metric_order = [
63
69
  RECALL_METRIC,
64
70
  LOAD_DURATION_METRIC,
65
71
  SERIAL_LATENCY_P99_METRIC,
72
+ SERIAL_LATENCY_P95_METRIC,
66
73
  MAX_LOAD_COUNT_METRIC,
67
74
  ]
68
75
 
vectordb_bench/models.py CHANGED
@@ -6,6 +6,9 @@ from typing import Self
6
6
 
7
7
  import ujson
8
8
 
9
+ from vectordb_bench.backend.cases import type2case
10
+ from vectordb_bench.backend.dataset import DatasetWithSizeMap
11
+
9
12
  from . import config
10
13
  from .backend.cases import Case, CaseType
11
14
  from .backend.clients import (
@@ -270,6 +273,21 @@ class TestResult(BaseModel):
270
273
  b = partial.json(exclude={"db_config": {"password", "api_key"}})
271
274
  f.write(b)
272
275
 
276
+ def get_case_config(case_config: CaseConfig) -> dict[CaseConfig]:
277
+ if case_config["case_id"] in {6, 7, 8, 9, 12, 13, 14, 15}:
278
+ case_instance = type2case[CaseType(case_config["case_id"])]()
279
+ custom_case = case_config["custom_case"]
280
+ if custom_case is None:
281
+ custom_case = {}
282
+ custom_case["filter_rate"] = case_instance.filter_rate
283
+ for dataset, size_type in DatasetWithSizeMap.items():
284
+ if case_instance.dataset == size_type:
285
+ custom_case["dataset_with_size_type"] = dataset
286
+ break
287
+ case_config["case_id"] = CaseType.NewIntFilterPerformanceCase
288
+ case_config["custom_case"] = custom_case
289
+ return case_config
290
+
273
291
  @classmethod
274
292
  def read_file(cls, full_path: pathlib.Path, trans_unit: bool = False) -> Self:
275
293
  if not full_path.exists():
@@ -280,10 +298,10 @@ class TestResult(BaseModel):
280
298
  test_result = ujson.loads(f.read())
281
299
  if "task_label" not in test_result:
282
300
  test_result["task_label"] = test_result["run_id"]
283
-
284
301
  for case_result in test_result["results"]:
285
- task_config = case_result["task_config"]
286
- db = DB(task_config["db"])
302
+ task_config = case_result.get("task_config")
303
+ case_config = task_config.get("case_config")
304
+ db = DB(task_config.get("db"))
287
305
 
288
306
  task_config["db_config"] = db.config_cls(**task_config["db_config"])
289
307
 
@@ -296,6 +314,7 @@ class TestResult(BaseModel):
296
314
  log.exception(f"Couldn't get class for index '{index_value}' ({full_path})")
297
315
  task_config["db_case_config"] = EmptyDBCaseConfig(**raw_case_cfg)
298
316
 
317
+ task_config["case_config"] = cls.get_case_config(case_config=case_config)
299
318
  case_result["task_config"] = task_config
300
319
 
301
320
  if trans_unit:
@@ -308,6 +327,16 @@ class TestResult(BaseModel):
308
327
  case_result["metrics"]["serial_latency_p99"] = (
309
328
  cur_latency * 1000 if cur_latency > 0 else cur_latency
310
329
  )
330
+
331
+ # Handle P95 latency for backward compatibility with existing result files
332
+ if "serial_latency_p95" in case_result["metrics"]:
333
+ cur_latency_p95 = case_result["metrics"]["serial_latency_p95"]
334
+ case_result["metrics"]["serial_latency_p95"] = (
335
+ cur_latency_p95 * 1000 if cur_latency_p95 > 0 else cur_latency_p95
336
+ )
337
+ else:
338
+ # Default to 0 for older result files that don't have P95 data
339
+ case_result["metrics"]["serial_latency_p95"] = 0.0
311
340
  return TestResult.validate(test_result)
312
341
 
313
342
  def display(self, dbs: list[DB] | None = None):
@@ -350,6 +379,7 @@ class TestResult(BaseModel):
350
379
  max_load_dur,
351
380
  max_qps,
352
381
  15,
382
+ 15,
353
383
  max_recall,
354
384
  14,
355
385
  5,
@@ -357,7 +387,7 @@ class TestResult(BaseModel):
357
387
 
358
388
  DATA_FORMAT = ( # noqa: N806
359
389
  f"%-{max_db}s | %-{max_db_labels}s %-{max_case}s %-{len(self.task_label)}s"
360
- f" | %-{max_load_dur}s %-{max_qps}s %-15s %-{max_recall}s %-14s"
390
+ f" | %-{max_load_dur}s %-{max_qps}s %-15s %-15s %-{max_recall}s %-14s"
361
391
  f" | %-5s"
362
392
  )
363
393
 
@@ -369,6 +399,7 @@ class TestResult(BaseModel):
369
399
  "load_dur",
370
400
  "qps",
371
401
  "latency(p99)",
402
+ "latency(p95)",
372
403
  "recall",
373
404
  "max_load_count",
374
405
  "label",
@@ -391,6 +422,7 @@ class TestResult(BaseModel):
391
422
  f.metrics.load_duration,
392
423
  f.metrics.qps,
393
424
  f.metrics.serial_latency_p99,
425
+ f.metrics.serial_latency_p95,
394
426
  f.metrics.recall,
395
427
  f.metrics.max_load_count,
396
428
  f.label.value,