Skip to content

Commit 519248a

Browse files
ScottLinnncopybara-github
authored andcommitted
Add BigQuery Conversational Analytics benchmark
PiperOrigin-RevId: 931307389
1 parent 0140863 commit 519248a

2 files changed

Lines changed: 701 additions & 0 deletions

File tree

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
# Copyright 2026 PerfKitBenchmarker Authors. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
r"""Runs Conversational Analytics performance benchmarks using BigQuery geminidataanalytics."""
16+
17+
import logging
18+
19+
from absl import flags
20+
from perfkitbenchmarker import configs
21+
from perfkitbenchmarker import edw_benchmark_results_aggregator as results_aggregator
22+
from perfkitbenchmarker import errors
23+
from perfkitbenchmarker import vm_util
24+
25+
BENCHMARK_NAME = 'edw_conversational_analytics_benchmark'
26+
27+
BENCHMARK_CONFIG = """
28+
edw_conversational_analytics_benchmark:
29+
description: Conversational Analytics performance benchmark using BigQuery.
30+
edw_service:
31+
type: bigquery
32+
cluster_identifier: _cluster_id_
33+
endpoint: cluster.endpoint
34+
db: _database_name_
35+
user: _username_
36+
password: _password_
37+
vm_groups:
38+
client:
39+
vm_spec: *default_dual_core
40+
"""
41+
42+
_DATASET = flags.DEFINE_enum(
43+
'dataset',
44+
'ecomm',
45+
['ecomm', 'call_center'],
46+
'The dataset to run: ecomm or call_center.',
47+
)
48+
49+
FLAGS = flags.FLAGS
50+
51+
52+
def GetConfig(user_config):
53+
return configs.LoadConfig(BENCHMARK_CONFIG, user_config, BENCHMARK_NAME)
54+
55+
56+
def CheckPrerequisites(_):
57+
if not FLAGS.bq_ca_agent:
58+
raise errors.Config.InvalidValue('Missing required flag: --bq_ca_agent')
59+
60+
61+
def Prepare(benchmark_spec):
62+
"""Install script execution environment on the client vm."""
63+
benchmark_spec.always_call_cleanup = True
64+
edw_service_instance = benchmark_spec.edw_service
65+
66+
# Assign provisioned attributes
67+
query_client = edw_service_instance.GetClientInterface()
68+
query_client.SetProvisionedAttributes(benchmark_spec)
69+
70+
ca_client = edw_service_instance.GetConversationalAnalyticsClientInterface()
71+
ca_client.SetProvisionedAttributes(benchmark_spec)
72+
benchmark_spec.ca_client = ca_client
73+
74+
# Prepare the client environment for both clients
75+
query_client.Prepare('edw_common')
76+
ca_client.Prepare('edw_common')
77+
78+
79+
def _RunConversationalQuery(q, ca_client, ca_iteration_performance):
80+
"""Ask the conversational analytics question and record performance."""
81+
execution_time, metadata = ca_client.ExecuteQuery(q.question)
82+
ca_iteration_performance.add_query_performance(
83+
q.question, execution_time, metadata
84+
)
85+
86+
87+
def _RunGroundTruthQuery(q, query_client, gt_iteration_performance):
88+
"""Execute ground truth SQL and record performance."""
89+
sql_file_name = f'{q.db_id}_gt.sql'
90+
vm_util.CreateRemoteFile(
91+
query_client.client_vm, q.ground_truth_sql, sql_file_name
92+
)
93+
gt_execution_time, gt_metadata = query_client.ExecuteQuery(
94+
sql_file_name, print_results=True
95+
)
96+
gt_metadata['question'] = q.question
97+
gt_metadata['ground_truth_sql'] = q.ground_truth_sql
98+
if 'query_results' in gt_metadata:
99+
gt_metadata['ground_truth_data'] = gt_metadata['query_results']
100+
else:
101+
logging.warning(
102+
'No query results found in ground truth query execution'
103+
' metadata: %s',
104+
gt_metadata,
105+
)
106+
gt_iteration_performance.add_query_performance(
107+
f'{q.question}_gt', gt_execution_time, gt_metadata
108+
)
109+
110+
111+
def _RunIteration(
112+
iteration_id,
113+
question_list,
114+
ca_client,
115+
query_client,
116+
ca_expected_queries,
117+
gt_expected_queries,
118+
):
119+
"""Run a single iteration of the benchmark suite."""
120+
ca_iteration_performance = results_aggregator.EdwPowerIterationPerformance(
121+
iteration_id=iteration_id, total_queries=len(ca_expected_queries)
122+
)
123+
gt_iteration_performance = results_aggregator.EdwPowerIterationPerformance(
124+
iteration_id=iteration_id, total_queries=len(gt_expected_queries)
125+
)
126+
127+
for q in question_list:
128+
_RunConversationalQuery(q, ca_client, ca_iteration_performance)
129+
_RunGroundTruthQuery(q, query_client, gt_iteration_performance)
130+
131+
return ca_iteration_performance, gt_iteration_performance
132+
133+
134+
def Run(benchmark_spec):
135+
"""Run phase executes conversational queries and collects latencies and metadata."""
136+
edw_service_instance = benchmark_spec.edw_service
137+
query_client = edw_service_instance.GetClientInterface()
138+
ca_client = benchmark_spec.ca_client
139+
140+
# Load dataset
141+
question_list = [
142+
q
143+
for q in edw_service_instance.GetConversationalAnalyticsQuestionList()
144+
if q.db_id == _DATASET.value
145+
]
146+
147+
# Determine expected queries (both the question and the ground truth)
148+
ca_expected_queries = [q.question for q in question_list]
149+
gt_expected_queries = [f'{q.question}_gt' for q in question_list]
150+
151+
# Accumulator for the entire benchmark's performance
152+
ca_performance = results_aggregator.EdwBenchmarkPerformance(
153+
total_iterations=FLAGS.edw_suite_iterations,
154+
expected_queries=ca_expected_queries,
155+
)
156+
gt_query_performance = results_aggregator.EdwBenchmarkPerformance(
157+
total_iterations=FLAGS.edw_suite_iterations,
158+
expected_queries=gt_expected_queries,
159+
)
160+
161+
# Multiple iterations of the suite
162+
for i in range(1, FLAGS.edw_suite_iterations + 1):
163+
ca_iter_perf, gt_iter_perf = _RunIteration(
164+
iteration_id=str(i),
165+
question_list=question_list,
166+
ca_client=ca_client,
167+
query_client=query_client,
168+
ca_expected_queries=ca_expected_queries,
169+
gt_expected_queries=gt_expected_queries,
170+
)
171+
ca_performance.add_iteration_performance(ca_iter_perf)
172+
gt_query_performance.add_iteration_performance(gt_iter_perf)
173+
174+
# Execution complete, generate results only if the benchmark was successful.
175+
if not gt_query_performance.is_successful():
176+
raise errors.Benchmarks.RunError(
177+
'Ground Truth query execution failed.'
178+
)
179+
180+
benchmark_metadata = {
181+
'agent': FLAGS.bq_ca_agent,
182+
'dataset': _DATASET.value,
183+
}
184+
benchmark_metadata.update(edw_service_instance.GetMetadata())
185+
186+
results = []
187+
results.extend(
188+
ca_performance.get_all_query_performance_samples(
189+
metadata=benchmark_metadata
190+
)
191+
)
192+
if ca_performance.is_successful():
193+
results.extend(
194+
ca_performance.get_queries_geomean_performance_samples(
195+
metadata=benchmark_metadata
196+
)
197+
)
198+
results.extend(
199+
gt_query_performance.get_all_query_performance_samples(
200+
metadata=benchmark_metadata
201+
)
202+
)
203+
results.extend(
204+
gt_query_performance.get_queries_geomean_performance_samples(
205+
metadata=benchmark_metadata
206+
)
207+
)
208+
209+
return results
210+
211+
212+
def Cleanup(benchmark_spec):
213+
benchmark_spec.edw_service.Cleanup()

0 commit comments

Comments
 (0)