vectordb-bench 0.0.16__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.
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/PKG-INFO +1 -1
- vectordb_bench-0.0.17/tests/test_rate_runner.py +88 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/__init__.py +1 -1
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/milvus/milvus.py +3 -2
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/dataset.py +8 -5
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/runner/mp_runner.py +94 -4
- vectordb_bench-0.0.17/vectordb_bench/backend/runner/rate_runner.py +79 -0
- vectordb_bench-0.0.17/vectordb_bench/backend/runner/read_write_runner.py +112 -0
- vectordb_bench-0.0.17/vectordb_bench/backend/runner/util.py +32 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/task_runner.py +5 -5
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/concurrent/charts.py +25 -9
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/concurrent.py +5 -1
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/metric.py +1 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/PKG-INFO +1 -1
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/SOURCES.txt +4 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/.devcontainer/Dockerfile +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/.devcontainer/devcontainer.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/.env.example +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/.github/workflows/publish_package_on_release.yml +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/.github/workflows/pull_request.yml +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/.gitignore +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/.ruff.toml +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/Dockerfile +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/LICENSE +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/Makefile +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/OWNERS +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/README.md +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/fig/custom_case_run_test.png +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/fig/custom_dataset.png +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/install/requirements_py3.11.txt +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/install.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/pyproject.toml +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/setup.cfg +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/conftest.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/pytest.ini +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_bench_runner.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_chroma.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_data_source.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_dataset.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_elasticsearch_cloud.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_models.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_redis.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/test_utils.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/tests/ut_cases.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/__main__.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/__init__.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/assembler.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/cases.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/__init__.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/api.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/aws_opensearch.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/aws_opensearch/run.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/chroma/chroma.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/chroma/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/elastic_cloud/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/elastic_cloud/elastic_cloud.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/memorydb/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/memorydb/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/memorydb/memorydb.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/milvus/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/milvus/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgdiskann/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgdiskann/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgdiskann/pgdiskann.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvecto_rs/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvecto_rs/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvecto_rs/pgvecto_rs.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvector/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvector/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvector/pgvector.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvectorscale/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvectorscale/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pgvectorscale/pgvectorscale.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pinecone/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/pinecone/pinecone.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/qdrant_cloud/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/qdrant_cloud/qdrant_cloud.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/redis/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/redis/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/redis/redis.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/test/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/test/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/test/test.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/weaviate_cloud/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/weaviate_cloud/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/weaviate_cloud/weaviate_cloud.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/zilliz_cloud/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/zilliz_cloud/config.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/zilliz_cloud/zilliz_cloud.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/data_source.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/result_collector.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/runner/__init__.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/runner/serial_runner.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/utils.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/base.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/cli/__init__.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/cli/cli.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/cli/vectordbbench.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/config-files/sample_config.yml +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/custom/custom_case.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/charts.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/data.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/expanderStyle.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/filters.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/footer.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/headerIcon.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/nav.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/priceTable.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/check_results/stPageConfig.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/displayCustomCase.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/displaypPrams.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/getCustomConfig.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/custom/initStyle.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/get_results/saveAsImage.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/autoRefresh.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/caseSelector.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/dbConfigSetting.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/dbSelector.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/generateTasks.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/hideSidebar.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/initStyle.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/run_test/submitTask.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/components/tables/data.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/config/dbCaseConfigs.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/config/dbPrices.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/config/styles.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/custom.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/quries_per_dollar.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/run_test.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/pages/tables.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/utils.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/frontend/vdb_benchmark.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/interface.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/log_util.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/models.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/ElasticCloud/result_20230727_standard_elasticcloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/ElasticCloud/result_20230808_standard_elasticcloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/Milvus/result_20230727_standard_milvus.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/Milvus/result_20230808_standard_milvus.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/PgVector/result_20230727_standard_pgvector.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/PgVector/result_20230808_standard_pgvector.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/Pinecone/result_20230727_standard_pinecone.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/Pinecone/result_20230808_standard_pinecone.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/QdrantCloud/result_20230727_standard_qdrantcloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/QdrantCloud/result_20230808_standard_qdrantcloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/WeaviateCloud/result_20230727_standard_weaviatecloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/WeaviateCloud/result_20230808_standard_weaviatecloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/ZillizCloud/result_20230727_standard_zillizcloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/ZillizCloud/result_20230808_standard_zillizcloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/ZillizCloud/result_20240105_standard_202401_zillizcloud.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/dbPrices.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/getLeaderboardData.py +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/results/leaderboard.json +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/dependency_links.txt +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/entry_points.txt +0 -0
- {vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench.egg-info/requires.txt +0 -0
- {vectordb_bench-0.0.16 → 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.
|
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",
|
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)
|
{vectordb_bench-0.0.16 → vectordb_bench-0.0.17}/vectordb_bench/backend/clients/milvus/milvus.py
RENAMED
@@ -66,7 +66,8 @@ class Milvus(VectorDB):
|
|
66
66
|
self.case_config.index_param(),
|
67
67
|
index_name=self._index_name,
|
68
68
|
)
|
69
|
-
|
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
|
@@ -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
|
-
|
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
|
-
|
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,
|
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
|
-
|
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()
|
@@ -6,7 +6,7 @@ import plotly.express as px
|
|
6
6
|
from vectordb_bench.frontend.config.styles import COLOR_MAP
|
7
7
|
|
8
8
|
|
9
|
-
def drawChartsByCase(allData, showCaseNames: list[str], st):
|
9
|
+
def drawChartsByCase(allData, showCaseNames: list[str], st, latency_type: str):
|
10
10
|
initMainExpanderStyle(st)
|
11
11
|
for caseName in showCaseNames:
|
12
12
|
chartContainer = st.expander(caseName, True)
|
@@ -14,15 +14,24 @@ def drawChartsByCase(allData, showCaseNames: list[str], st):
|
|
14
14
|
data = [
|
15
15
|
{
|
16
16
|
"conc_num": caseData["conc_num_list"][i],
|
17
|
-
"qps": caseData["conc_qps_list"][i]
|
18
|
-
|
17
|
+
"qps": caseData["conc_qps_list"][i]
|
18
|
+
if 0 <= i < len(caseData["conc_qps_list"])
|
19
|
+
else 0,
|
20
|
+
"latency_p99": caseData["conc_latency_p99_list"][i] * 1000
|
21
|
+
if 0 <= i < len(caseData["conc_latency_p99_list"])
|
22
|
+
else 0,
|
23
|
+
"latency_avg": caseData["conc_latency_avg_list"][i] * 1000
|
24
|
+
if 0 <= i < len(caseData["conc_latency_avg_list"])
|
25
|
+
else 0,
|
19
26
|
"db_name": caseData["db_name"],
|
20
27
|
"db": caseData["db"],
|
21
28
|
}
|
22
29
|
for caseData in caseDataList
|
23
30
|
for i in range(len(caseData["conc_num_list"]))
|
24
31
|
]
|
25
|
-
drawChart(
|
32
|
+
drawChart(
|
33
|
+
data, chartContainer, key=f"{caseName}-qps-p99", x_metric=latency_type
|
34
|
+
)
|
26
35
|
|
27
36
|
|
28
37
|
def getRange(metric, data, padding_multipliers):
|
@@ -36,14 +45,21 @@ def getRange(metric, data, padding_multipliers):
|
|
36
45
|
return rangeV
|
37
46
|
|
38
47
|
|
39
|
-
def
|
48
|
+
def gen_title(s: str) -> str:
|
49
|
+
if "latency" in s:
|
50
|
+
return f'{s.replace("_", " ").title()} (ms)'
|
51
|
+
else:
|
52
|
+
return s.upper()
|
53
|
+
|
54
|
+
|
55
|
+
def drawChart(data, st, key: str, x_metric: str = "latency_p99", y_metric: str = "qps"):
|
40
56
|
if len(data) == 0:
|
41
57
|
return
|
42
58
|
|
43
|
-
x =
|
59
|
+
x = x_metric
|
44
60
|
xrange = getRange(x, data, [0.05, 0.1])
|
45
61
|
|
46
|
-
y =
|
62
|
+
y = y_metric
|
47
63
|
yrange = getRange(y, data, [0.2, 0.1])
|
48
64
|
|
49
65
|
color = "db"
|
@@ -69,8 +85,8 @@ def drawChart(data, st, key: str):
|
|
69
85
|
},
|
70
86
|
height=720,
|
71
87
|
)
|
72
|
-
fig.update_xaxes(range=xrange, title_text=
|
73
|
-
fig.update_yaxes(range=yrange, title_text=
|
88
|
+
fig.update_xaxes(range=xrange, title_text=gen_title(x_metric))
|
89
|
+
fig.update_yaxes(range=yrange, title_text=gen_title(y_metric))
|
74
90
|
fig.update_traces(textposition="bottom right", texttemplate="conc-%{text:,.4~r}")
|
75
91
|
|
76
92
|
st.plotly_chart(fig, use_container_width=True, key=key)
|
@@ -55,7 +55,11 @@ def main():
|
|
55
55
|
resultesContainer = st.sidebar.container()
|
56
56
|
getResults(resultesContainer, "vectordb_bench_concurrent")
|
57
57
|
|
58
|
-
|
58
|
+
# main
|
59
|
+
latency_type = st.radio("Latency Type", options=["latency_p99", "latency_avg"])
|
60
|
+
drawChartsByCase(
|
61
|
+
shownData, showCaseNames, st.container(), latency_type=latency_type
|
62
|
+
)
|
59
63
|
|
60
64
|
# footer
|
61
65
|
footer(st.container())
|
@@ -23,6 +23,7 @@ class Metric:
|
|
23
23
|
conc_num_list: list[int] = field(default_factory=list)
|
24
24
|
conc_qps_list: list[float] = field(default_factory=list)
|
25
25
|
conc_latency_p99_list: list[float] = field(default_factory=list)
|
26
|
+
conc_latency_avg_list: list[float] = field(default_factory=list)
|
26
27
|
|
27
28
|
|
28
29
|
QURIES_PER_DOLLAR_METRIC = "QP$ (Quries per Dollar)"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: vectordb-bench
|
3
|
-
Version: 0.0.
|
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
|