dev/stackdiff-dtrace: stack aggregation diffing script (#1373)
Motivation: NIO has allocation counter tests, NIO also has dev/malloc-aggregation.d which can give you aggregated stacks that allocated alongside how many times they allocated. What's missing is a script that can diff two aggregated stack traces. Modifications: Add dev/stacktrace-dtrace which allows aggregated stack trace diffing. Result: Easier to track performance regressions.
This commit is contained in:
parent
a8fe2f343b
commit
a76a98eb00
|
@ -0,0 +1,93 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
##===----------------------------------------------------------------------===##
|
||||||
|
##
|
||||||
|
## This source file is part of the SwiftNIO open source project
|
||||||
|
##
|
||||||
|
## Copyright (c) 2020 Apple Inc. and the SwiftNIO project authors
|
||||||
|
## Licensed under Apache License v2.0
|
||||||
|
##
|
||||||
|
## See LICENSE.txt for license information
|
||||||
|
## See CONTRIBUTORS.txt for the list of SwiftNIO project authors
|
||||||
|
##
|
||||||
|
## SPDX-License-Identifier: Apache-2.0
|
||||||
|
##
|
||||||
|
##===----------------------------------------------------------------------===##
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
num_regex = "^ +([0-9a-fx]+)$"
|
||||||
|
stack_regex = "^ +(.*)$"
|
||||||
|
|
||||||
|
def put_in_dict(path):
|
||||||
|
dictionary = {}
|
||||||
|
with open(path, "r") as f:
|
||||||
|
current_text = ""
|
||||||
|
for line in f:
|
||||||
|
if line == "":
|
||||||
|
break
|
||||||
|
if re.match(num_regex, line):
|
||||||
|
key = "\n".join(map(lambda l: l.strip().split("+")[0],
|
||||||
|
current_text.split("\n")[0:8]))
|
||||||
|
dictionary[key] = (int(line), current_text)
|
||||||
|
current_text = ""
|
||||||
|
elif line.strip() == "":
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
current_text = current_text + line.strip() + "\n"
|
||||||
|
return dictionary
|
||||||
|
|
||||||
|
def extract_useful_keys(d):
|
||||||
|
keys = set()
|
||||||
|
for k in d.keys():
|
||||||
|
if d[k][0] > 1000:
|
||||||
|
keys.add(k)
|
||||||
|
return keys
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print("Usage: stackdiff-dtrace.py OLD-STACKS NEW-STACKS")
|
||||||
|
print()
|
||||||
|
print("stackdiff-dtrace can diff aggregated stack traces as produced")
|
||||||
|
print("by a `agg[ustack()] = count();` and printed with `printa(agg)`;")
|
||||||
|
print("by a dtrace program.")
|
||||||
|
print()
|
||||||
|
print("Full example leveraging the malloc aggregation:")
|
||||||
|
print(" # get old stack traces")
|
||||||
|
print(" sudo malloc-aggregation.d -c ./old-binary > /tmp/old")
|
||||||
|
print(" # get new stack traces")
|
||||||
|
print(" sudo malloc-aggregation.d -c ./new-binary > /tmp/new")
|
||||||
|
print(" # diff them")
|
||||||
|
print(" stackdiff-dtrace.py /tmp/old /tmp/new")
|
||||||
|
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
usage()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
before_file = sys.argv[1]
|
||||||
|
after_file = sys.argv[2]
|
||||||
|
|
||||||
|
after_dict = put_in_dict(before_file)
|
||||||
|
before_dict = put_in_dict(after_file)
|
||||||
|
|
||||||
|
useful_after_keys = extract_useful_keys(after_dict)
|
||||||
|
useful_before_keys = extract_useful_keys(before_dict)
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print("### only in AFTER")
|
||||||
|
for x in sorted(list(useful_after_keys - useful_before_keys)):
|
||||||
|
print(after_dict[x][0])
|
||||||
|
print(after_dict[x][1])
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print("### only in BEFORE")
|
||||||
|
for x in sorted(list(useful_before_keys - useful_after_keys)):
|
||||||
|
print(before_dict[x][0])
|
||||||
|
print(before_dict[x][1])
|
||||||
|
|
||||||
|
print("")
|
||||||
|
print("### different numbers")
|
||||||
|
for x in sorted(list(useful_before_keys & useful_after_keys)):
|
||||||
|
if after_dict[x][0] != before_dict[x][0]:
|
||||||
|
print("before: %d, after: %d" % (before_dict[x][0],
|
||||||
|
after_dict[x][0]))
|
||||||
|
print(after_dict[x][1])
|
|
@ -36,7 +36,7 @@ fi
|
||||||
printf "=> Checking license headers... "
|
printf "=> Checking license headers... "
|
||||||
tmp=$(mktemp /tmp/.swift-nio-sanity_XXXXXX)
|
tmp=$(mktemp /tmp/.swift-nio-sanity_XXXXXX)
|
||||||
|
|
||||||
for language in swift-or-c bash dtrace; do
|
for language in swift-or-c bash dtrace python; do
|
||||||
declare -a matching_files
|
declare -a matching_files
|
||||||
declare -a exceptions
|
declare -a exceptions
|
||||||
expections=( )
|
expections=( )
|
||||||
|
@ -78,6 +78,25 @@ EOF
|
||||||
## SPDX-License-Identifier: Apache-2.0
|
## SPDX-License-Identifier: Apache-2.0
|
||||||
##
|
##
|
||||||
##===----------------------------------------------------------------------===##
|
##===----------------------------------------------------------------------===##
|
||||||
|
EOF
|
||||||
|
;;
|
||||||
|
python)
|
||||||
|
matching_files=( -name '*.py' )
|
||||||
|
cat > "$tmp" <<"EOF"
|
||||||
|
#!/usr/bin/env python
|
||||||
|
##===----------------------------------------------------------------------===##
|
||||||
|
##
|
||||||
|
## This source file is part of the SwiftNIO open source project
|
||||||
|
##
|
||||||
|
## Copyright (c) YEARS Apple Inc. and the SwiftNIO project authors
|
||||||
|
## Licensed under Apache License v2.0
|
||||||
|
##
|
||||||
|
## See LICENSE.txt for license information
|
||||||
|
## See CONTRIBUTORS.txt for the list of SwiftNIO project authors
|
||||||
|
##
|
||||||
|
## SPDX-License-Identifier: Apache-2.0
|
||||||
|
##
|
||||||
|
##===----------------------------------------------------------------------===##
|
||||||
EOF
|
EOF
|
||||||
;;
|
;;
|
||||||
dtrace)
|
dtrace)
|
||||||
|
|
Loading…
Reference in New Issue