-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specify multiple search clients for easier benchmarking #614
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,8 @@ | |
import io | ||
import logging | ||
import sys | ||
import re | ||
from enum import Enum | ||
|
||
import tabulate | ||
|
||
|
@@ -43,6 +45,11 @@ | |
------------------------------------------------------ | ||
""" | ||
|
||
class Throughput(Enum): | ||
MEAN = "mean" | ||
MAX = "max" | ||
MIN = "min" | ||
MEDIAN = "median" | ||
|
||
def summarize(results, cfg): | ||
SummaryResultsPublisher(results, cfg).publish() | ||
|
@@ -126,6 +133,17 @@ def __init__(self, results, config): | |
"throughput":comma_separated_string_to_number_list(config.opts("workload", "throughput.percentiles", mandatory=False)), | ||
"latency": comma_separated_string_to_number_list(config.opts("workload", "latency.percentiles", mandatory=False)) | ||
} | ||
self.logger = logging.getLogger(__name__) | ||
|
||
def publish_operational_statistics(self, metrics_table: list, warnings: list, record, task): | ||
metrics_table.extend(self._publish_throughput(record, task)) | ||
metrics_table.extend(self._publish_latency(record, task)) | ||
metrics_table.extend(self._publish_service_time(record, task)) | ||
# this is mostly needed for debugging purposes but not so relevant to end users | ||
if self.show_processing_time: | ||
metrics_table.extend(self._publish_processing_time(record, task)) | ||
metrics_table.extend(self._publish_error_rate(record, task)) | ||
self.add_warnings(warnings, record, task) | ||
|
||
def publish(self): | ||
print_header(FINAL_SCORE) | ||
|
@@ -145,16 +163,33 @@ def publish(self): | |
|
||
metrics_table.extend(self._publish_transform_stats(stats)) | ||
|
||
# These variables are used with the clients_list parameter in test_procedures to find the max throughput. | ||
max_throughput = -1 | ||
record_with_best_throughput = None | ||
|
||
throughput_pattern = r"_(\d+)_clients$" | ||
|
||
|
||
for record in stats.op_metrics: | ||
task = record["task"] | ||
metrics_table.extend(self._publish_throughput(record, task)) | ||
metrics_table.extend(self._publish_latency(record, task)) | ||
metrics_table.extend(self._publish_service_time(record, task)) | ||
# this is mostly needed for debugging purposes but not so relevant to end users | ||
if self.show_processing_time: | ||
metrics_table.extend(self._publish_processing_time(record, task)) | ||
metrics_table.extend(self._publish_error_rate(record, task)) | ||
self.add_warnings(warnings, record, task) | ||
is_task_part_of_throughput_testing = re.search(throughput_pattern, task) | ||
if is_task_part_of_throughput_testing: | ||
# assumption: all units are the same and only maximizing throughput over one operation (i.e. not both ingest and search). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Putting emphasis on this comment. Right now search clients is the main use case for vector search (users want to see search throughput from inference perspective). I think adding support for multiple clients in any operation can be deferred to a later PR. Any thoughts? |
||
# To maximize throughput over multiple operations, would need a list/dictionary of maximum throughputs. | ||
task_throughput = record["throughput"][Throughput.MEAN.value] | ||
self.logger.info("Task %s has throughput %s", task, task_throughput) | ||
if task_throughput > max_throughput: | ||
max_throughput = task_throughput | ||
record_with_best_throughput = record | ||
|
||
else: | ||
self.publish_operational_statistics(metrics_table=metrics_table, warnings=warnings, record=record, task=task) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Would be nice if there was another comment above this if statement to stating that the following blurb is related to throughput testing / when specifying multiple clients within the operation |
||
# The following code is run when the clients_list parameter is specified and publishes the max throughput. | ||
if max_throughput != -1 and record_with_best_throughput is not None: | ||
self.publish_operational_statistics(metrics_table=metrics_table, warnings=warnings, record=record_with_best_throughput, | ||
task=record_with_best_throughput["task"]) | ||
metrics_table.extend(self._publish_best_client_settings(record_with_best_throughput, record_with_best_throughput["task"])) | ||
|
||
for record in stats.correctness_metrics: | ||
task = record["task"] | ||
|
@@ -217,6 +252,10 @@ def _publish_recall(self, values, task): | |
self._line("Mean recall@1", task, recall_1_mean, "", lambda v: "%.2f" % v) | ||
) | ||
|
||
def _publish_best_client_settings(self, record, task): | ||
num_clients = re.search(r"_(\d+)_clients$", task).group(1) | ||
return self._join(self._line("Number of clients that achieved max throughput", "", num_clients, "")) | ||
|
||
def _publish_percentiles(self, name, task, value, unit="ms"): | ||
lines = [] | ||
percentiles = self.display_percentiles.get(name, metrics.GlobalStatsCalculator.OTHER_PERCENTILES) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Would also add a comment above this to specify that the following three variables are related to
clients_list
parameter in test_procedures. Newcomers might not quickly understand that this is only relevant to throughput testing clients