mirror of https://github.com/grpc/grpc.git
Add per-call memory bloat report to CI (#29037)
* Add per-call memory bloat report to CI * fix * test * Automated change: Fix sanity tests * Update grpc_bloat_diff_in_docker.sh * Update memory_diff.py * review feedback * prep for new job Co-authored-by: ctiller <ctiller@users.noreply.github.com>pull/29081/head
parent
4ffcef7932
commit
5d81683faa
4 changed files with 184 additions and 6 deletions
@ -0,0 +1,28 @@ |
||||
#!/usr/bin/env bash |
||||
# Copyright 2017 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. |
||||
|
||||
set -ex |
||||
|
||||
# Enter the gRPC repo root |
||||
cd $(dirname $0)/../../.. |
||||
|
||||
source tools/internal_ci/helper_scripts/prepare_build_linux_rc |
||||
|
||||
export DOCKERFILE_DIR=tools/dockerfile/test/cxx_debian11_x64 |
||||
export DOCKER_RUN_SCRIPT=tools/internal_ci/linux/grpc_memory_diff_in_docker.sh |
||||
# The check_on_pr.py needs access to the key to post status on github PRs, |
||||
# so we mount the keystore dir to the docker container. |
||||
export EXTRA_DOCKER_ARGS="-v ${KOKORO_KEYSTORE_DIR}:/kokoro_keystore -e KOKORO_KEYSTORE_DIR=/kokoro_keystore" |
||||
exec tools/run_tests/dockerize/build_and_run_docker.sh |
@ -0,0 +1,28 @@ |
||||
#!/usr/bin/env bash |
||||
# Copyright 2022 The 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. |
||||
|
||||
set -ex |
||||
|
||||
# Enter the gRPC repo root |
||||
cd $(dirname $0)/../../.. |
||||
|
||||
# some extra pip packages are needed for the check_on_pr.py script to work |
||||
# TODO(jtattermusch): avoid needing to install these pip packages each time |
||||
time python3 -m pip install --user -r tools/internal_ci/helper_scripts/requirements.linux_perf.txt |
||||
|
||||
tools/run_tests/start_port_server.py |
||||
|
||||
tools/internal_ci/linux/run_if_c_cpp_modified.sh tools/profiling/memory/memory_diff.py \ |
||||
-d "origin/$KOKORO_GITHUB_PULL_REQUEST_TARGET_BRANCH" |
@ -0,0 +1,107 @@ |
||||
#!/usr/bin/env python3 |
||||
# |
||||
# Copyright 2022 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. |
||||
|
||||
import argparse |
||||
import csv |
||||
import glob |
||||
import math |
||||
import multiprocessing |
||||
import os |
||||
import pathlib |
||||
import re |
||||
import shutil |
||||
import subprocess |
||||
import sys |
||||
|
||||
sys.path.append( |
||||
os.path.join(os.path.dirname(sys.argv[0]), '..', '..', 'run_tests', |
||||
'python_utils')) |
||||
import check_on_pr |
||||
|
||||
argp = argparse.ArgumentParser(description='Perform diff on memory benchmarks') |
||||
|
||||
argp.add_argument('-d', |
||||
'--diff_base', |
||||
type=str, |
||||
help='Commit or branch to compare the current one to') |
||||
|
||||
argp.add_argument('-j', '--jobs', type=int, default=multiprocessing.cpu_count()) |
||||
|
||||
args = argp.parse_args() |
||||
|
||||
_INTERESTING = { |
||||
'client call': |
||||
(rb'client call memory usage: ([0-9\.]+) bytes per call', float), |
||||
'server call': |
||||
(rb'server call memory usage: ([0-9\.]+) bytes per call', float), |
||||
} |
||||
|
||||
|
||||
def _run(): |
||||
"""Build with Bazel, then run, and extract interesting lines from the output.""" |
||||
subprocess.check_call([ |
||||
'tools/bazel', 'build', '-c', 'opt', |
||||
'test/core/memory_usage/memory_usage_test' |
||||
]) |
||||
output = subprocess.check_output([ |
||||
'bazel-bin/test/core/memory_usage/memory_usage_test', |
||||
'--warmup=10000', |
||||
'--benchmark=50000', |
||||
]) |
||||
ret = {} |
||||
for line in output.splitlines(): |
||||
for key, (pattern, conversion) in _INTERESTING.items(): |
||||
m = re.match(pattern, line) |
||||
if m: |
||||
ret[key] = conversion(m.group(1)) |
||||
return ret |
||||
|
||||
|
||||
cur = _run() |
||||
new = None |
||||
|
||||
print(cur) |
||||
|
||||
if args.diff_base: |
||||
where_am_i = subprocess.check_output( |
||||
['git', 'rev-parse', '--abbrev-ref', 'HEAD']).decode().strip() |
||||
# checkout the diff base (="old") |
||||
subprocess.check_call(['git', 'checkout', args.diff_base]) |
||||
try: |
||||
new = _run() |
||||
finally: |
||||
# restore the original revision (="new") |
||||
subprocess.check_call(['git', 'checkout', where_am_i]) |
||||
|
||||
text = '' |
||||
if new is None: |
||||
for key, value in cur.items(): |
||||
text += '{}: {}\n'.format(key, value) |
||||
else: |
||||
diff_size = 0 |
||||
for key, value in _INTERESTING.items(): |
||||
if key in cur: |
||||
if key not in new: |
||||
text += '{}: {}\n'.format(key, value) |
||||
else: |
||||
diff_size += cur[key] - new[key] |
||||
text += '{}: {} -> {}\n'.format(key, cur[key], new[key]) |
||||
|
||||
print("DIFF_SIZE: %f" % diff_size) |
||||
check_on_pr.label_increase_decrease_on_pr('per-call-memory', diff_size, 64) |
||||
|
||||
print(text) |
||||
check_on_pr.check_on_pr('Memory Difference', '```\n%s\n```' % text) |
Loading…
Reference in new issue