mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
4.0 KiB
138 lines
4.0 KiB
#!/usr/bin/env python3 |
|
|
|
# Copyright 2023 gRPC authors. |
|
# |
|
# Licensed under the Apache License, Version 2.0 (the "License"); |
|
# you may not use this file except in compliance with the License. |
|
# You may obtain a copy of the License at |
|
# |
|
# http://www.apache.org/licenses/LICENSE-2.0 |
|
# |
|
# Unless required by applicable law or agreed to in writing, software |
|
# distributed under the License is distributed on an "AS IS" BASIS, |
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
# See the License for the specific language governing permissions and |
|
# limitations under the License. |
|
""" |
|
Local QPS benchmark runner for the OSS Benchmark loadtest configurations. |
|
|
|
This tool will run a scenario locally, either already extracted from |
|
scenario_config_exporter, or extracted from a benchmark loadtest config. The |
|
driver, client, and server all in the same process. You can run the process |
|
under a custom runner using the --runner_cmd="<COMMAND>" flag, and with custom |
|
environment variables if needed. |
|
|
|
This example will run an optimized build of the loadtest under gdb |
|
|
|
GRPC_VERBOSITY=debug \ |
|
bazel run \ |
|
--config=opt \ |
|
--cxxopt="-gmlt" \ |
|
test/cpp/qps:scenario_runner -- \ |
|
--loadtest_file=/path/to/loadtest.config \ |
|
--runner_cmd="gdb --args" |
|
|
|
This builds the binary and runs: |
|
|
|
gdb --args bazel-bin/.../scenario_runner -- \ |
|
--loadtest_config=/tmp/path/extracted_scenario_json.config |
|
|
|
|
|
If you have already extracted the JSON scenario using scenario_config_exporter, |
|
you can replace `--loadtest_file=loadtest.yaml` with |
|
`--scenario_file=scenario.json`. |
|
|
|
|
|
Other --runner_cmd examples: |
|
--runner_cmd="perf record -F 777 -o $(pwd)/perf.data -g --event=cpu-cycles", |
|
--runner_cmd="perf stat record -o $(pwd)/perf.stat.data", |
|
" |
|
""" |
|
|
|
|
|
import os |
|
import subprocess |
|
import sys |
|
import tempfile |
|
|
|
from absl import app |
|
from absl import flags |
|
import yaml |
|
|
|
_LOADTEST_YAML = flags.DEFINE_string( |
|
"loadtest_file", default=None, help="Path to the benchmark loadtest file" |
|
) |
|
_SCENARIO_JSON = flags.DEFINE_string( |
|
"scenario_file", default=None, help="Path to a scenario JSON file" |
|
) |
|
_RUNNER_CMD = flags.DEFINE_string( |
|
"runner_cmd", |
|
default="", |
|
help="Run the scearnio runner under a custom command (example: bazel ... --cmd='perf lock record -o $(pwd)/out')", |
|
) |
|
_RUN_FIRST = flags.DEFINE_bool( |
|
"run_first", |
|
default=False, |
|
help="Only run the first scenario in the loadtest", |
|
) |
|
_RUN_ALL = flags.DEFINE_bool( |
|
"run_all", default=False, help="Run all scenarios in the loadtest" |
|
) |
|
|
|
|
|
def run_command(filename): |
|
cmd = [ |
|
os.path.join( |
|
os.path.dirname(os.path.abspath(__file__)), |
|
"scenario_runner_cc", |
|
), |
|
"--loadtest_config", |
|
filename, |
|
] |
|
if _RUNNER_CMD.value: |
|
cmd = _RUNNER_CMD.value.split(" ") + cmd |
|
print(cmd) |
|
subprocess.run(cmd, check=True) |
|
if _RUN_FIRST.value: |
|
print("Exiting due to --run_first") |
|
sys.exit(0) |
|
|
|
|
|
def run_loadtests(): |
|
loadtests = [] |
|
with open( |
|
os.path.join( |
|
os.path.dirname(os.path.abspath(__file__)), _LOADTEST_YAML.value |
|
) |
|
) as f: |
|
loadtests = list(yaml.safe_load_all(f)) |
|
if len(loadtests) > 1 and not (_RUN_FIRST.value or _RUN_ALL.value): |
|
print( |
|
"The loadtest configuration file contains more than one loadtest. Please specify --run_first or --run_all.", |
|
file=sys.stderr, |
|
) |
|
sys.exit(1) |
|
for loadtest in loadtests: |
|
with tempfile.NamedTemporaryFile() as tmp_f: |
|
tmp_f.write( |
|
"".join(loadtest["spec"]["scenariosJSON"]).encode("utf-8") |
|
) |
|
tmp_f.flush() |
|
run_command(tmp_f.name) |
|
|
|
|
|
def run_scenario_file(): |
|
run_command(_SCENARIO_JSON.value) |
|
|
|
|
|
def main(args): |
|
if _LOADTEST_YAML.value: |
|
run_loadtests() |
|
elif _SCENARIO_JSON.value: |
|
run_scenario_file() |
|
else: |
|
"You must provide either a scenario.json or loadtest.yaml" |
|
|
|
|
|
if __name__ == "__main__": |
|
app.run(main)
|
|
|