-
Notifications
You must be signed in to change notification settings - Fork 83
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
query_namespaces performance improvements (#417)
## Problem Want to improve the performance of the rest implementation of `query_namespaces` ## Solution - Add `pytest-benchmark` dev dependency and some basic performance tests to interrogate the impact of certain changes. For now these are only run on my local machine, but in the future these could potentially be expanded into an automated suite. - Pass `_preload_content=False` to tell the underlying generated code not to instantiate response objects for all the intermediate results. - Use `ThreadPoolExecutor` instead of older `ThreadPool` implementation from multiprocessing. This involved some changes to the generated code, but the benefit of this approach is that you get back a `concurrent.futures.Future` instead of an `ApplyResult` which is much more ergonomic. I'm planning to extract the edited files out of the code gen process very shortly, so there shouldn't be a concern about modifying generated files in this case. I gated this approach behind a new kwarg, `async_threadpool_executor`, that lives alongside `async_req`; eventually I would like to replace all usage of `async_req`'s ThreadPool with ThreadPoolExecutor to bring the rest and grpc implementations closer together, but I can't do that in this PR without creating a breaking change. The net effect of these changes seems to be about ~18% performance improvement. ## Type of Change - [ ] Bug fix (non-breaking change which fixes an issue) - [x] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update - [ ] Infrastructure change (CI configs, etc) - [ ] Non-code change (docs, etc) - [ ] None of the above: (explain here)
- Loading branch information
Showing
7 changed files
with
172 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import time | ||
import random | ||
import pytest | ||
from pinecone import Pinecone | ||
from pinecone.grpc import PineconeGRPC | ||
|
||
latencies = [] | ||
|
||
|
||
def call_n_threads(index): | ||
query_vec = [random.random() for i in range(1024)] | ||
start = time.time() | ||
combined_results = index.query_namespaces( | ||
vector=query_vec, | ||
namespaces=["ns1", "ns2", "ns3", "ns4"], | ||
include_values=False, | ||
include_metadata=True, | ||
filter={"publication_date": {"$eq": "Last3Months"}}, | ||
top_k=1000, | ||
) | ||
finish = time.time() | ||
# print(f"Query took {finish-start} seconds") | ||
latencies.append(finish - start) | ||
|
||
return combined_results | ||
|
||
|
||
class TestQueryNamespacesRest: | ||
@pytest.mark.parametrize("n_threads", [4]) | ||
def test_query_namespaces_grpc(self, benchmark, n_threads): | ||
pc = PineconeGRPC() | ||
index = pc.Index( | ||
host="jen1024-dojoi3u.svc.apw5-4e34-81fa.pinecone.io", pool_threads=n_threads | ||
) | ||
benchmark.pedantic(call_n_threads, (index,), rounds=10, warmup_rounds=1, iterations=5) | ||
|
||
@pytest.mark.parametrize("n_threads", [4]) | ||
def test_query_namespaces_rest(self, benchmark, n_threads): | ||
pc = Pinecone() | ||
index = pc.Index( | ||
host="jen1024-dojoi3u.svc.apw5-4e34-81fa.pinecone.io", | ||
pool_threads=n_threads, | ||
connection_pool_maxsize=20, | ||
) | ||
benchmark.pedantic(call_n_threads, (index,), rounds=10, warmup_rounds=1, iterations=5) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import random | ||
from pinecone.data.query_results_aggregator import QueryResultsAggregator | ||
|
||
|
||
def fake_results(i): | ||
matches = [ | ||
{"id": f"id{i}", "score": random.random(), "values": [random.random() for _ in range(768)]} | ||
for _ in range(1000) | ||
] | ||
matches.sort(key=lambda x: x["score"], reverse=True) | ||
return {"namespace": f"ns{i}", "matches": matches} | ||
|
||
|
||
def aggregate_results(responses): | ||
ag = QueryResultsAggregator(1000) | ||
for response in responses: | ||
ag.add_results(response) | ||
return ag.get_results() | ||
|
||
|
||
class TestQueryResultsAggregatorPerf: | ||
def test_my_stuff(self, benchmark): | ||
responses = [fake_results(i) for i in range(10)] | ||
benchmark(aggregate_results, responses) |