[emscripten] Add code size test script
And a second code size test for testing dead code elimination.
Produces output like this:
Type , File , Size , Gzip , Brotli
Debug , emdawnwebgpu_init_only.js , 103861 , 28197 , 24169
Release , emdawnwebgpu_init_only.js , 9038 , 4090 , 3627
MinSizeRel , emdawnwebgpu_init_only.js , 9038 , 4090 , 3629
Debug , emdawnwebgpu_init_only.wasm , 2573142 , 569846 , 433061
Release , emdawnwebgpu_init_only.wasm , 24031 , 9468 , 7908
MinSizeRel , emdawnwebgpu_init_only.wasm , 22738 , 9290 , 7892
Debug , emdawnwebgpu_link_test.js , 169877 , 37549 , 31579
Release , emdawnwebgpu_link_test.js , 30874 , 10954 , 9572
MinSizeRel , emdawnwebgpu_link_test.js , 30874 , 10960 , 9577
Debug , emdawnwebgpu_link_test.wasm , 2710280 , 581164 , 436289
Release , emdawnwebgpu_link_test.wasm , 40268 , 14751 , 12048
MinSizeRel , emdawnwebgpu_link_test.wasm , 38676 , 14623 , 12119
Bug: 377760848
Change-Id: I3d882df0fcb6c6819f9b0205e59d0b9c8ba1930d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/255560
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
diff --git a/.github/workflows/package-emdawnwebgpu.sh b/.github/workflows/package-emdawnwebgpu.sh
index b8974f3..9c6f69b 100755
--- a/.github/workflows/package-emdawnwebgpu.sh
+++ b/.github/workflows/package-emdawnwebgpu.sh
@@ -54,6 +54,9 @@
# Switch the build type (in-place to save time), rebuild the link test (this
# time with Closure, which verifies the linked JS to some extent), and build the
# final package (which is not actually affected by build type).
+# TODO: If we have Ninja (from depot_tools), we could use -G'Ninja Multi-Config'
+# to do multiple build types more cleanly.
+# https://cmake.org/cmake/help/latest/generator/Ninja%20Multi-Config.html
cmake -S=. -B=out/wasm -DCMAKE_BUILD_TYPE=Release
make -j4 -C out/wasm emdawnwebgpu_pkg emdawnwebgpu_link_test
diff --git a/src/emdawnwebgpu/CMakeLists.txt b/src/emdawnwebgpu/CMakeLists.txt
index 033fb6e..21c8ce6 100644
--- a/src/emdawnwebgpu/CMakeLists.txt
+++ b/src/emdawnwebgpu/CMakeLists.txt
@@ -336,6 +336,7 @@
"-sJSPI=1"
)
+ # A "sample" that makes real (bogus) API calls to serve as a basic code size test.
DawnJSONGenerator(
TARGET "emdawnwebgpu_link_test_cpp"
PRINT_NAME "emdawnwebgpu LinkTest.cpp"
@@ -347,7 +348,6 @@
# The test is just that this links, not that it runs (it will just
# crash), so just build to .js. Since it has a main() function, this is
# the same as building to .html, but skipping the .html file.
- # This makes real (bogus) API calls to serve as a basic code size test.
set_target_properties(emdawnwebgpu_link_test PROPERTIES
SUFFIX ".js")
target_link_libraries(
@@ -356,5 +356,19 @@
emdawnwebgpu_test_linkopts
emdawnwebgpu_c
)
+
+ # A "sample" that just creates a device. This is used to check the code size for the
+ # elimination of unused library code.
+ add_executable(emdawnwebgpu_init_only_sample
+ "InitOnlySample.cpp"
+ )
+ set_target_properties(emdawnwebgpu_init_only_sample PROPERTIES
+ SUFFIX ".js")
+ target_link_libraries(
+ emdawnwebgpu_init_only_sample
+ PUBLIC
+ emdawnwebgpu_test_linkopts
+ emdawnwebgpu_cpp
+ )
endif()
endif()
diff --git a/src/emdawnwebgpu/InitOnlySample.cpp b/src/emdawnwebgpu/InitOnlySample.cpp
new file mode 100644
index 0000000..4288d22
--- /dev/null
+++ b/src/emdawnwebgpu/InitOnlySample.cpp
@@ -0,0 +1,49 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Standalone sample that only initializes a device, to test
+// dead-code-elimination of the rest of the library.
+
+#include <webgpu/webgpu_cpp.h>
+
+#include <utility>
+
+int main() {
+ auto instance = wgpu::CreateInstance();
+
+ wgpu::Adapter adapter = nullptr;
+ instance.WaitAny(
+ instance.RequestAdapter(nullptr, wgpu::CallbackMode::AllowSpontaneous,
+ [&adapter](wgpu::RequestAdapterStatus, wgpu::Adapter a,
+ wgpu::StringView) { adapter = std::move(a); }),
+ UINT64_MAX);
+
+ instance.WaitAny(
+ adapter.RequestDevice(nullptr, wgpu::CallbackMode::AllowSpontaneous,
+ [](wgpu::RequestDeviceStatus, wgpu::Device, wgpu::StringView) {}),
+ UINT64_MAX);
+}
diff --git a/src/emdawnwebgpu/test_code_size.sh b/src/emdawnwebgpu/test_code_size.sh
new file mode 100755
index 0000000..5423c0b
--- /dev/null
+++ b/src/emdawnwebgpu/test_code_size.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+# Copyright 2025 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Script for manual use to quickly test the code size of various targets for use when doing code
+# size optimization work. Outputs CSV to stdout (and logging to stderr), so can be used like so:
+#
+# $ ./src/emdawnwebgpu/test_code_size.sh | tee before.txt
+
+set -euo pipefail
+
+script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+cd "$script_dir/../.."
+
+targets=(emdawnwebgpu_init_only emdawnwebgpu_link_test)
+parts=(js wasm)
+types=(Debug Release MinSizeRel)
+
+echo -e '#### Compiling (output on stderr)... ####\n' >&2
+
+outdir=out/emdawnwebgpu_code_size
+mkdir -p "$outdir"
+cd "$outdir"
+
+# Use the Ninja Multi-Config target because CMake configuration takes a long time.
+../../third_party/emsdk/upstream/emscripten/emcmake cmake ../.. -G'Ninja Multi-Config' \
+ -DCMAKE_CONFIGURATION_TYPES="$(IFS=';' ; echo "${types[*]}")" 1>&2
+for type in "${types[@]}" ; do
+ cmake --build . --config="$type" --target "${targets[@]}" 1>&2
+done
+
+echo -e '\n#### Compilation done. Printing CSV results to stdout. ####\n' >&2
+
+fmt_string='%10s , %-27s , %8s , %8s , %8s\n'
+printf "$fmt_string" "Type" "File" "Size" "Gzip" "Brotli"
+for target in "${targets[@]}" ; do
+ for part in "${parts[@]}" ; do
+ for type in "${types[@]}" ; do
+ filename="$target.$part"
+ filepath="$type/$target.$part"
+ printf "$fmt_string" "$type" "$filename" "$(wc -c < $filepath)" "$(gzip -9 < $filepath | wc -c)" "$(brotli < $filepath | wc -c)"
+ done
+ done
+done