| #!/usr/bin/env bash | |
| # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file | |
| # for details. All rights reserved. Use of this source code is governed by a | |
| # BSD-style license that can be found in the LICENSE file. | |
| # Script to compile a benchmark using dart2wasm. Assumes the Dart repo's | |
| # directory structure. | |
| set -e | |
| function follow_links() { | |
| file="$1" | |
| while [ -h "$file" ]; do | |
| # On Mac OS, readlink -f doesn't work. | |
| file="$(readlink "$file")" | |
| done | |
| echo "$file" | |
| } | |
| # Unlike $0, $BASH_SOURCE points to the absolute path of this file. | |
| PROG_NAME="$(follow_links "$BASH_SOURCE")" | |
| # Handle the case where dart-sdk/bin has been symlinked to. | |
| PROG_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" | |
| source "$PROG_DIR/utils.sh" | |
| BINARYEN="$BIN_DIR/wasm-opt" | |
| RUN_BINARYEN=1 | |
| RUN_SRC=0 | |
| GENERATE_SOURCE_MAP=1 | |
| COMPILE_BENCHMARK_BASE_NAME="" | |
| PLATFORM_FILENAME="$BIN_DIR/dart2wasm_platform.dill" | |
| SNAPSHOT_NAME="dart2wasm" | |
| RUN_BENCHMARK=0 | |
| USE_TEMP_OUTPUT=0 | |
| # All arguments will be passed along to dart2wasm except specially recognized | |
| # flags. | |
| VM_ARGS=() | |
| DART2WASM_ARGS=() | |
| DART_FILE="" | |
| OUTPUT_FILE="" | |
| PHASES="" | |
| while [ $# -gt 0 ]; do | |
| case "$1" in | |
| --compile-benchmark=*) | |
| COMPILE_BENCHMARK_BASE_NAME=$(echo $1 | sed 's/--compile-benchmark=//g') | |
| shift | |
| ;; | |
| --src) | |
| RUN_SRC=1 | |
| shift | |
| ;; | |
| --run) | |
| RUN_BENCHMARK=1 | |
| RUN_BENCHMARK_SHELL="d8" | |
| shift | |
| ;; | |
| --run=*) | |
| RUN_BENCHMARK=1 | |
| RUN_BENCHMARK_SHELL="${1#--run=}" | |
| shift | |
| ;; | |
| --temp-output) | |
| USE_TEMP_OUTPUT=1 | |
| shift | |
| ;; | |
| --js-compatibility) | |
| PLATFORM_FILENAME="$BIN_DIR/dart2wasm_js_compatibility_platform.dill" | |
| DART2WASM_ARGS+=("--js-compatibility") | |
| shift | |
| ;; | |
| --standalone) | |
| PLATFORM_FILENAME="$BIN_DIR/dart2wasm_standalone_platform.dill" | |
| DART2WASM_ARGS+=("--standalone") | |
| shift | |
| ;; | |
| --compiler-asserts) | |
| SNAPSHOT_NAME="dart2wasm_asserts" | |
| VM_ARGS+=("--enable-asserts") | |
| shift | |
| ;; | |
| -O0 | --optimization-level=0 | --extra-compiler-option=-O0 ) | |
| DART2WASM_ARGS+=("-O0") | |
| RUN_BINARYEN=0 | |
| shift | |
| ;; | |
| -O* | --optimization-level=*) | |
| DART2WASM_ARGS+=("$1") | |
| RUN_BINARYEN=1 | |
| shift | |
| ;; | |
| --phases=*) | |
| PHASES="${1#--phases=}" | |
| shift | |
| ;; | |
| --extra-compiler-option=--platform=*) | |
| PLATFORM_FILENAME="${1#--extra-compiler-option=--platform=}" | |
| shift | |
| ;; | |
| --extra-compiler-option=--no-js-compatibility) | |
| PLATFORM_FILENAME="$BIN_DIR/dart2wasm_platform.dill" | |
| DART2WASM_ARGS+=("--no-js-compatibility") | |
| shift | |
| ;; | |
| --extra-compiler-option=*) | |
| DART2WASM_ARGS+=("${1#--extra-compiler-option=}") | |
| shift | |
| ;; | |
| --no-source-maps) | |
| GENERATE_SOURCE_MAP=0 | |
| shift | |
| ;; | |
| -o) | |
| shift | |
| OUTPUT_FILE="$1" | |
| shift | |
| ;; | |
| --* | -*) | |
| DART2WASM_ARGS+=("$1") | |
| shift | |
| ;; | |
| *) | |
| if [ -z "$DART_FILE" ]; then | |
| DART_FILE="$1" | |
| shift | |
| else | |
| if [ -z "$OUTPUT_FILE" ]; then | |
| OUTPUT_FILE="$1" | |
| shift | |
| else | |
| echo "Unexpected argument $1" | |
| exit 1 | |
| fi | |
| fi | |
| ;; | |
| esac | |
| done | |
| if [ -z "$DART_FILE" ]; then | |
| echo "Expected <file.dart> [file.wasm]" | |
| exit 1 | |
| fi | |
| if [ $USE_TEMP_OUTPUT -eq 1 ] && [ -n "$OUTPUT_FILE" ]; then | |
| echo "Cannot specify both --temp-output and an explicit output file!" | |
| exit 1 | |
| fi | |
| if [ $USE_TEMP_OUTPUT -eq 0 ] && [ -z "$OUTPUT_FILE" ]; then | |
| echo "Expected <file.dart> <file.wasm>" | |
| exit 1 | |
| fi | |
| if [ $USE_TEMP_OUTPUT -eq 1 ]; then | |
| BASENAME=$(basename "$DART_FILE" .dart) | |
| TEMP_DIR=$(mktemp -d) | |
| trap "rm -rf $TEMP_DIR" EXIT | |
| OUTPUT_FILE="$TEMP_DIR/${BASENAME}.wasm" | |
| echo "Compiling to temporary file: $OUTPUT_FILE" | |
| fi | |
| if [ -z "$PHASES" ]; then | |
| PHASES="cfe,tfa,codegen" | |
| fi | |
| PLATFORM_ARG="--platform=$PLATFORM_FILENAME" | |
| DART2WASM_AOT_SNAPSHOT="$BIN_DIR/$SNAPSHOT_NAME.snapshot" | |
| DART2WASM_SRC="$SDK_DIR/pkg/dart2wasm/bin/dart2wasm.dart" | |
| function measure() { | |
| set +e | |
| RESULT=$( { /usr/bin/time --format="\nMemory: %M KB, Time: %e s" "$@"; } 2>&1 ) | |
| EXIT=$? | |
| if [ $EXIT -ne 0 ]; then | |
| echo "Running $@ resulted in exit code $EXIT" | |
| echo "$RESULT" | |
| exit 1 | |
| fi | |
| set -e | |
| MEMORY=$(echo "$RESULT" | tail -n1 | sed 's/Memory: \([0-9.]\+\) KB, Time: \([0-9.]\+\) s.*/\1/g') | |
| MEMORY=$(($MEMORY * 1024)) | |
| TIME=$(echo "$RESULT" | tail -n1 | sed 's/Memory: \([0-9.]\+\) KB, Time: \([0-9.]\+\) s.*/\2/g') | |
| } | |
| function measure_size() { | |
| SIZE=$(cat $1 | wc -c) | |
| GZIP_SIZE=$(cat $1 | gzip -c6 | wc -c) | |
| } | |
| function run_if_binaryen_enabled() { | |
| if [ $RUN_BINARYEN -eq 1 ] && [[ $OUTPUT_FILE == *.wasm ]]; then | |
| "$@" | |
| fi | |
| } | |
| COMPILER_SIZE=0 | |
| COMPILER_GZIP_SIZE=0 | |
| if [ $RUN_SRC -eq 1 ]; then | |
| BASE_CMD=("$DART" "${VM_ARGS[@]}" "$DART2WASM_SRC" "$LIBRARIES_JSON_ARG") | |
| else | |
| BASE_CMD=("$DART_AOT_RUNTIME" "${VM_ARGS[@]}" "$DART2WASM_AOT_SNAPSHOT" "$PLATFORM_ARG") | |
| fi | |
| function run_compiler() { | |
| local dart2wasm_command=("${BASE_CMD[@]}" "${DART2WASM_ARGS[@]}" "--phases=$PHASES" "$DART_FILE" "$OUTPUT_FILE") | |
| if [ -n "$COMPILE_BENCHMARK_BASE_NAME" ]; then | |
| measure "${dart2wasm_command[@]}" | |
| COMPILER_TIME=$TIME | |
| COMPILER_MEMORY=$MEMORY | |
| measure_size "${OUTPUT_FILE%.wasm}.mjs" | |
| MJS_SIZE=$SIZE | |
| MJS_GZIP_SIZE=$GZIP_SIZE | |
| for OUTPUT_FILE in "${OUTPUT_FILE%.wasm}"*.wasm; do | |
| measure_size "$OUTPUT_FILE" | |
| (( COMPILER_SIZE+=$SIZE )) | |
| (( COMPILER_GZIP_SIZE+=$GZIP_SIZE )) | |
| done | |
| else | |
| "${dart2wasm_command[@]}" | |
| fi | |
| } | |
| BINARYEN_TIME=0 | |
| BINARYEN_MEMORY=0 | |
| BINARYEN_SIZE=0 | |
| BINARYEN_GZIP_SIZE=0 | |
| function run_binaryen() { | |
| local opt_command=("${BASE_CMD[@]}" "${DART2WASM_ARGS[@]}" "--phases=opt" "--wasm-opt=$BINARYEN" "$OUTPUT_FILE" "$OUTPUT_FILE") | |
| if [ -n "$COMPILE_BENCHMARK_BASE_NAME" ]; then | |
| # If we're measuring run each binaryen command sequentially. | |
| measure "${opt_command[@]}" | |
| BINARYEN_TIME=$(echo "$BINARYEN_TIME + $TIME" | bc) | |
| BINARYEN_MEMORY=$(($BINARYEN_MEMORY > $MEMORY ? $BINARYEN_MEMORY : $MEMORY )) | |
| measure_size "$OUTPUT_FILE" | |
| BINARYEN_SIZE=$(echo "$BINARYEN_SIZE + $SIZE" | bc) | |
| BINARYEN_GZIP_SIZE=$(echo "$BINARYEN_GZIP_SIZE + $GZIP_SIZE" | bc) | |
| MAX_MEMORY=$(($COMPILER_MEMORY > $BINARYEN_MEMORY ? $COMPILER_MEMORY : $BINARYEN_MEMORY )) | |
| TOTAL_TIME=$(echo "$COMPILER_TIME + $BINARYEN_TIME" | bc) | |
| else | |
| "${opt_command[@]}" | |
| fi | |
| } | |
| run_compiler | |
| run_if_binaryen_enabled run_binaryen | |
| if [ -n "$COMPILE_BENCHMARK_BASE_NAME" ]; then | |
| # CompileTime | |
| run_if_binaryen_enabled echo "$COMPILE_BENCHMARK_BASE_NAME.Time.Total(CompileTime): $TOTAL_TIME s" | |
| echo "$COMPILE_BENCHMARK_BASE_NAME.Time.Dart2Wasm(CompileTime): $COMPILER_TIME s" | |
| run_if_binaryen_enabled echo "$COMPILE_BENCHMARK_BASE_NAME.Time.Wasm2WasmOpt(CompileTime): $BINARYEN_TIME s" | |
| # CodeSize | |
| echo "$COMPILE_BENCHMARK_BASE_NAME.Size.mjs(CodeSize): $MJS_SIZE bytes" | |
| echo "$COMPILE_BENCHMARK_BASE_NAME.Size.mjs.gz(CodeSize): $MJS_GZIP_SIZE bytes" | |
| echo "$COMPILE_BENCHMARK_BASE_NAME.Size.wasm(CodeSize): $COMPILER_SIZE bytes" | |
| echo "$COMPILE_BENCHMARK_BASE_NAME.Size.wasm.gz(CodeSize): $COMPILER_GZIP_SIZE bytes" | |
| run_if_binaryen_enabled echo "$COMPILE_BENCHMARK_BASE_NAME.Size.wasm.opt(CodeSize): $BINARYEN_SIZE bytes" | |
| run_if_binaryen_enabled echo "$COMPILE_BENCHMARK_BASE_NAME.Size.wasm.opt.gz(CodeSize): $BINARYEN_GZIP_SIZE bytes" | |
| # MemoryUse | |
| run_if_binaryen_enabled echo "$COMPILE_BENCHMARK_BASE_NAME.MemoryUse.Max(MemoryUse): $MAX_MEMORY bytes" | |
| echo "$COMPILE_BENCHMARK_BASE_NAME.MemoryUse.Dart2Wasm(MemoryUse): $COMPILER_MEMORY bytes" | |
| run_if_binaryen_enabled echo "$COMPILE_BENCHMARK_BASE_NAME.MemoryUse.Wasm2WasmOpt(MemoryUse): $BINARYEN_MEMORY bytes" | |
| fi | |
| if [ $RUN_BENCHMARK -eq 1 ]; then | |
| echo "" | |
| echo "RUNNING $OUTPUT_FILE" | |
| "$PROG_DIR/run_benchmark" "--$RUN_BENCHMARK_SHELL" "$OUTPUT_FILE" | |
| fi |