|
|
@@ -41,22 +41,52 @@ readonly GOOGLE_PROTOBUF_CHECKOUT=${GOOGLE_PROTOBUF_CHECKOUT:-"$script_dir/../..
|
|
|
|
|
|
function usage() {
|
|
|
cat >&2 <<EOF
|
|
|
-Usage: $0 [-p <true|false>] [-s2|-s3] <field count> <field types...>
|
|
|
-
|
|
|
-Currently supported field types:
|
|
|
- int32, sint32, uint32, fixed32, sfixed32,
|
|
|
- int64, sint64, uint64, fixed64, sfixed64,
|
|
|
- float, double, string,
|
|
|
- ...and repeated variants of the above.
|
|
|
-
|
|
|
- Additionally, you can specify "all" to run the harness
|
|
|
- multiple times with all of the (non-repeated) field types
|
|
|
- listed above.
|
|
|
-
|
|
|
-Options:
|
|
|
- -p <true|false>: Adds a packed option to each field.
|
|
|
- -s[23]: Generate proto2 or proto3 syntax. proto3 is
|
|
|
- the default.
|
|
|
+SYNOPSIS
|
|
|
+ $0 [-c <rev|c++> -c <rev|c++> ...] [-p <true|false>] [-s2|-s3] <field count> <field types...>
|
|
|
+
|
|
|
+ Currently supported field types:
|
|
|
+ int32, sint32, uint32, fixed32, sfixed32,
|
|
|
+ int64, sint64, uint64, fixed64, sfixed64,
|
|
|
+ float, double, string,
|
|
|
+ ...and repeated variants of the above.
|
|
|
+
|
|
|
+ Additionally, you can specify "all" to run the harness multiple
|
|
|
+ times with all of the (non-repeated) field types listed above.
|
|
|
+ ("all" is not compatible with revision comparisons.)
|
|
|
+
|
|
|
+OPTIONS
|
|
|
+ -c <rev|c++> [-c <rev|c++> ...]
|
|
|
+ A git revision (a commit hash, branch name, or tag) or the
|
|
|
+ string "c++" that will be performance tested and added as a
|
|
|
+ series in the result plot to compare against the current
|
|
|
+ working tree state. Can be specified multiple times. The current
|
|
|
+ working tree is always tested and included as the final series.
|
|
|
+
|
|
|
+ If no "-c" options are specified, the working tree is compared
|
|
|
+ against the C++ implementation.
|
|
|
+
|
|
|
+ -p <true|false>
|
|
|
+ If true, the generator adds a packed option to each field.
|
|
|
+ Defaults to false.
|
|
|
+
|
|
|
+ -s2, -s3
|
|
|
+ Indicates whether proto2 or proto3 syntax should be generated.
|
|
|
+ The default is proto3.
|
|
|
+
|
|
|
+EXAMPLES
|
|
|
+ $0 100 fixed32
|
|
|
+ Runs the C++ harness and Swift harness in the current working
|
|
|
+ tree using a message with 100 fixed32 fields.
|
|
|
+
|
|
|
+ $0 -c string-speedup -p true 100 "repeated string"
|
|
|
+ Runs the Swift harness in its state at branch "string-speedup"
|
|
|
+ and then again in the current working tree, using a message
|
|
|
+ with 100 packed repeated string fields.
|
|
|
+
|
|
|
+ $0 -c 4d0b78 -c c++ -s2 100 bytes
|
|
|
+ Runs the Swift harness in its state at commit 4d0b78, the C++
|
|
|
+ harness, and then the Swift harness in the current working tree,
|
|
|
+ using a proto2 message with 100 bytes fields.
|
|
|
EOF
|
|
|
exit 1
|
|
|
}
|
|
|
@@ -106,7 +136,9 @@ function run_harness_and_concatenate_results() {
|
|
|
partial_results="$3"
|
|
|
|
|
|
cat >> "$partial_results" <<EOF
|
|
|
- "$language": {
|
|
|
+ {
|
|
|
+ name: "$language",
|
|
|
+ data: {
|
|
|
EOF
|
|
|
|
|
|
echo "Running $language test harness alone..."
|
|
|
@@ -124,21 +156,23 @@ EOF
|
|
|
echo
|
|
|
|
|
|
cat >> "$partial_results" <<EOF
|
|
|
- harnessSize: {
|
|
|
- "Unstripped": $unstripped_size,
|
|
|
- "Stripped": $stripped_size,
|
|
|
+ harnessSize: {
|
|
|
+ "Unstripped": $unstripped_size,
|
|
|
+ "Stripped": $stripped_size,
|
|
|
+ },
|
|
|
},
|
|
|
},
|
|
|
EOF
|
|
|
}
|
|
|
|
|
|
function profile_harness() {
|
|
|
- language="$1"
|
|
|
+ description="$1"
|
|
|
harness="$2"
|
|
|
+ perf_dir="$3"
|
|
|
|
|
|
- echo "Running $language test harness in Instruments..."
|
|
|
+ echo "Running $description test harness in Instruments..."
|
|
|
instruments -t "$script_dir/Protobuf" -D "$results_trace" \
|
|
|
- "$harness" -e DYLD_LIBRARY_PATH "$script_dir/_generated"
|
|
|
+ "$harness" -e DYLD_LIBRARY_PATH "$perf_dir/_generated"
|
|
|
}
|
|
|
|
|
|
# Inserts the partial visualization results from all the languages tested into
|
|
|
@@ -156,19 +190,38 @@ function insert_visualization_results() {
|
|
|
mv "${results_js}.new" "$results_js"
|
|
|
}
|
|
|
|
|
|
-# ---------------------------------------------------------------
|
|
|
-# Pull in language specific helpers.
|
|
|
-source "$script_dir/perf_runner_cpp.sh"
|
|
|
-source "$script_dir/perf_runner_swift.sh"
|
|
|
+# build_swift_packages <workdir> <plugin_suffix>
|
|
|
+#
|
|
|
+# Builds the runtime and plug-in with Swift Package Manager, assuming the
|
|
|
+# package manifest and sources are in <workdir>. After being built, the
|
|
|
+# plug-in will be copied and renamed to "protoc-gen-swift<plugin_suffix>"
|
|
|
+# in the same release directory, so that it can be guaranteed unique when
|
|
|
+# running protoc.
|
|
|
+function build_swift_packages() {
|
|
|
+ workdir="$1"
|
|
|
+ plugin_suffix="$2"
|
|
|
+ (
|
|
|
+ echo "Building runtime and plug-in with Swift Package Manager..."
|
|
|
+
|
|
|
+ cd "$workdir" >/dev/null
|
|
|
+ swift build -c release >/dev/null
|
|
|
+ cp .build/release/protoc-gen-swift \
|
|
|
+ ".build/release/protoc-gen-swift${plugin_suffix}"
|
|
|
+ )
|
|
|
+}
|
|
|
|
|
|
# ---------------------------------------------------------------
|
|
|
-# Script main logic.
|
|
|
+# Process command line options.
|
|
|
|
|
|
+declare -a comparisons
|
|
|
packed=""
|
|
|
proto_syntax="3"
|
|
|
|
|
|
-while getopts "p:s:" arg; do
|
|
|
+while getopts "c:p:s:" arg; do
|
|
|
case "${arg}" in
|
|
|
+ c)
|
|
|
+ comparisons+=("$OPTARG")
|
|
|
+ ;;
|
|
|
p)
|
|
|
packed="$OPTARG"
|
|
|
;;
|
|
|
@@ -198,13 +251,23 @@ else
|
|
|
readonly requested_field_types=( "$@" )
|
|
|
fi
|
|
|
|
|
|
-# Make sure the runtime and plug-in are up to date first.
|
|
|
-( cd "$script_dir/.." >/dev/null; swift build -c release )
|
|
|
+# ---------------------------------------------------------------
|
|
|
+# Set up a hook to cleanup revision comparison checkouts when the script
|
|
|
+# completes.
|
|
|
+declare -a CLEANUP_WHEN_DONE
|
|
|
+function cleanup_revision_checkouts() {
|
|
|
+ if [[ "${#CLEANUP_WHEN_DONE[@]}" -ne 0 ]]; then
|
|
|
+ rm -rf "${CLEANUP_WHEN_DONE[@]}"
|
|
|
+ fi
|
|
|
+}
|
|
|
+trap cleanup_revision_checkouts EXIT HUP INT QUIT TERM
|
|
|
|
|
|
-# Copy the newly built plugin with a new name so that we can ensure that we're
|
|
|
-# invoking the correct one when we pass it on the command line.
|
|
|
-cp "$script_dir/../.build/release/protoc-gen-swift" \
|
|
|
- "$script_dir/../.build/release/protoc-gen-swiftForPerf"
|
|
|
+# ---------------------------------------------------------------
|
|
|
+# Pull in language-specific runners.
|
|
|
+source "$script_dir/runners/swift.sh"
|
|
|
+
|
|
|
+# ---------------------------------------------------------------
|
|
|
+# Script main logic.
|
|
|
|
|
|
mkdir -p "$script_dir/_generated"
|
|
|
mkdir -p "$script_dir/_results"
|
|
|
@@ -217,39 +280,94 @@ if [[ ! -f "$results_js" ]]; then
|
|
|
fi
|
|
|
|
|
|
# Iterate over the requested field types and run the harnesses.
|
|
|
+# TODO: Get rid of this multi-run; instead, just create a proto like
|
|
|
+# TestAllTypes that tests multiple field types in one message. This is more
|
|
|
+# realistic.
|
|
|
for field_type in "${requested_field_types[@]}"; do
|
|
|
gen_message_path="$script_dir/_generated/message.proto"
|
|
|
|
|
|
echo "Generating test proto with $field_count fields of type $field_type..."
|
|
|
generate_test_proto "$field_count" "$field_type"
|
|
|
|
|
|
- protoc --plugin="$script_dir/../.build/release/protoc-gen-swiftForPerf" \
|
|
|
- --swiftForPerf_out=FileNaming=DropPath:"$script_dir/_generated" \
|
|
|
- --cpp_out="$script_dir" \
|
|
|
- "$gen_message_path"
|
|
|
-
|
|
|
# Start a session.
|
|
|
partial_results="$script_dir/_results/partial.js"
|
|
|
+ pretty_head_rev="$(git rev-parse --abbrev-ref HEAD)"
|
|
|
cat > "$partial_results" <<EOF
|
|
|
{
|
|
|
date: "$(date -u +"%FT%T.000Z")",
|
|
|
type: "$field_count fields of type $field_type",
|
|
|
- branch: "$(git rev-parse --abbrev-ref HEAD)",
|
|
|
+ branch: "$pretty_head_rev",
|
|
|
commit: "$(git rev-parse HEAD)",
|
|
|
uncommitted_changes: $([[ -z $(git status -s) ]] && echo false || echo true),
|
|
|
+ series: [
|
|
|
EOF
|
|
|
|
|
|
- harness_cpp="$script_dir/_generated/harness_cpp"
|
|
|
- results_trace="$script_dir/_results/$field_count fields of $field_type (cpp)"
|
|
|
- run_cpp_harness "$harness_cpp"
|
|
|
+ for comparison in "${comparisons[@]}"; do
|
|
|
+ if [[ "$comparison" == "c++" ]]; then
|
|
|
+ source "$script_dir/runners/cpp.sh"
|
|
|
+
|
|
|
+ echo
|
|
|
+ echo "==== Building/running C++ harness ===================="
|
|
|
+ echo
|
|
|
+
|
|
|
+ protoc --cpp_out="$script_dir" "$gen_message_path"
|
|
|
+
|
|
|
+ harness_cpp="$script_dir/_generated/harness_cpp"
|
|
|
+ results_trace="$script_dir/_results/$field_count fields of $field_type (cpp)"
|
|
|
+ run_cpp_harness "$harness_cpp"
|
|
|
+ else
|
|
|
+ commit_hash="$(git rev-parse $comparison)"
|
|
|
+ commit_results="$script_dir/_results/${commit_hash}_${field_type}_${field_count}.js"
|
|
|
+
|
|
|
+ # Check to see if we have past results from that commit cached. If so, we
|
|
|
+ # don't need to run it again.
|
|
|
+ if [[ ! -f "$commit_results" ]]; then
|
|
|
+ echo
|
|
|
+ echo "==== Building/running Swift harness ($comparison) ===================="
|
|
|
+ echo
|
|
|
+
|
|
|
+ # Check out the commit to a temporary directory and create its _generated
|
|
|
+ # directory. (Results will still go in the working tree.)
|
|
|
+ tmp_checkout="$(mktemp -d -t swiftprotoperf)"
|
|
|
+ CLEANUP_WHEN_DONE+=("$tmp_checkout")
|
|
|
+ git --work-tree="$tmp_checkout" checkout "$comparison" -- .
|
|
|
+ mkdir "$tmp_checkout/Performance/_generated"
|
|
|
+
|
|
|
+ build_swift_packages "$tmp_checkout" "ForRev"
|
|
|
+ protoc --plugin="$tmp_checkout/.build/release/protoc-gen-swiftForRev" \
|
|
|
+ --swiftForRev_out=FileNaming=DropPath:"$tmp_checkout/Performance/_generated" \
|
|
|
+ "$gen_message_path"
|
|
|
+
|
|
|
+ harness_swift="$tmp_checkout/Performance/_generated/harness_swift"
|
|
|
+ results_trace="$script_dir/_results/$field_count fields of $field_type (swift)"
|
|
|
+ run_swift_harness "$tmp_checkout" "$comparison" "$commit_results"
|
|
|
+ else
|
|
|
+ echo
|
|
|
+ echo "==== Found cached results for Swift ($comparison) ===================="
|
|
|
+ fi
|
|
|
+
|
|
|
+ cat "$commit_results" >> "$partial_results"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ echo
|
|
|
+ echo "==== Building/running Swift harness (working tree) ===================="
|
|
|
+ echo
|
|
|
+
|
|
|
+ build_swift_packages "$script_dir/.." "ForWorkTree"
|
|
|
+ protoc --plugin="$script_dir/../.build/release/protoc-gen-swiftForWorkTree" \
|
|
|
+ --swiftForWorkTree_out=FileNaming=DropPath:"$script_dir/_generated" \
|
|
|
+ --cpp_out="$script_dir" \
|
|
|
+ "$gen_message_path"
|
|
|
|
|
|
harness_swift="$script_dir/_generated/harness_swift"
|
|
|
results_trace="$script_dir/_results/$field_count fields of $field_type (swift)"
|
|
|
display_results_trace="$results_trace"
|
|
|
- run_swift_harness "$harness_swift"
|
|
|
+ run_swift_harness "$script_dir/.." "working tree" "$partial_results"
|
|
|
|
|
|
# Close out the session.
|
|
|
cat >> "$partial_results" <<EOF
|
|
|
+ ],
|
|
|
},
|
|
|
EOF
|
|
|
|