From 4397e30f7d0f56be1556b187b73103606112c141 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Aug 2026 19:27:20 +0000 Subject: [PATCH 1/4] [Autoloop: perf-comparison] Iteration 482: add wasm_agg_ops benchmark pair Run: https://github.com/githubnext/tsb/actions/runs/32766310388 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- benchmarks/pandas/bench_wasm_agg_ops.py | 51 +++++++++++++++++++++ benchmarks/tsb/bench_wasm_agg_ops.ts | 60 +++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 benchmarks/pandas/bench_wasm_agg_ops.py create mode 100644 benchmarks/tsb/bench_wasm_agg_ops.ts diff --git a/benchmarks/pandas/bench_wasm_agg_ops.py b/benchmarks/pandas/bench_wasm_agg_ops.py new file mode 100644 index 00000000..0b44ec3b --- /dev/null +++ b/benchmarks/pandas/bench_wasm_agg_ops.py @@ -0,0 +1,51 @@ +""" +Benchmark: numpy aggregate operations — np.sum, np.mean, np.min, np.max, np.var, np.std, np.median +plus pandas rolling and expanding window ops on a 100k-element float64 array. + +Mirrors tsb bench_wasm_agg_ops.ts. + +Outputs JSON: {"function": "wasm_agg_ops", "mean_ms": ..., "iterations": ..., "total_ms": ...} +""" +import json +import time +import numpy as np +import pandas as pd + +SIZE = 100_000 +WINDOW = 50 +MIN_PERIODS = 1 +WARMUP = 3 +ITERATIONS = 20 + +data = np.sin(np.arange(SIZE) * 0.001) * 1000 +series = pd.Series(data) + + +def run(): + np.sum(data) + np.mean(data) + np.min(data) + np.max(data) + np.var(data, ddof=1) + np.std(data, ddof=1) + np.median(data) + series.rolling(window=WINDOW, min_periods=MIN_PERIODS).sum() + series.rolling(window=WINDOW, min_periods=MIN_PERIODS).mean() + series.expanding(min_periods=MIN_PERIODS).sum() + series.expanding(min_periods=MIN_PERIODS).mean() + + +for _ in range(WARMUP): + run() + +start = time.perf_counter() +for _ in range(ITERATIONS): + run() +total = (time.perf_counter() - start) * 1000 # ms + +print(json.dumps({ + "function": "wasm_agg_ops", + "mean_ms": total / ITERATIONS, + "iterations": ITERATIONS, + "total_ms": total, +})) diff --git a/benchmarks/tsb/bench_wasm_agg_ops.ts b/benchmarks/tsb/bench_wasm_agg_ops.ts new file mode 100644 index 00000000..2b615e65 --- /dev/null +++ b/benchmarks/tsb/bench_wasm_agg_ops.ts @@ -0,0 +1,60 @@ +/** + * Benchmark: WASM-accelerated aggregate operations — sumF64Accelerated, meanF64Accelerated, + * minF64Accelerated, maxF64Accelerated, varF64Accelerated, stdF64Accelerated, medianF64Accelerated + * plus rolling and expanding variants on a 100k-element float64 array. + * + * Mirrors numpy aggregate functions (np.sum, np.mean, np.min, np.max, np.var, np.std, np.median) + * and pandas rolling/expanding window ops. + * + * Outputs JSON: {"function": "wasm_agg_ops", "mean_ms": ..., "iterations": ..., "total_ms": ...} + */ +import { + sumF64Accelerated, + meanF64Accelerated, + minF64Accelerated, + maxF64Accelerated, + varF64Accelerated, + stdF64Accelerated, + medianF64Accelerated, + rollingSumF64Accelerated, + rollingMeanF64Accelerated, + expandingSumF64Accelerated, + expandingMeanF64Accelerated, +} from "../../src/wasm/index.ts"; + +const SIZE = 100_000; +const WINDOW = 50; +const MIN_PERIODS = 1; +const WARMUP = 3; +const ITERATIONS = 20; + +const data: number[] = Array.from({ length: SIZE }, (_, i) => Math.sin(i * 0.001) * 1000); + +function run(): void { + sumF64Accelerated(data); + meanF64Accelerated(data); + minF64Accelerated(data); + maxF64Accelerated(data); + varF64Accelerated(data); + stdF64Accelerated(data); + medianF64Accelerated(data); + rollingSumF64Accelerated(data, WINDOW, MIN_PERIODS); + rollingMeanF64Accelerated(data, WINDOW, MIN_PERIODS); + expandingSumF64Accelerated(data, MIN_PERIODS); + expandingMeanF64Accelerated(data, MIN_PERIODS); +} + +for (let i = 0; i < WARMUP; i++) run(); + +const start = performance.now(); +for (let i = 0; i < ITERATIONS; i++) run(); +const total = performance.now() - start; + +console.log( + JSON.stringify({ + function: "wasm_agg_ops", + mean_ms: total / ITERATIONS, + iterations: ITERATIONS, + total_ms: total, + }), +); From bb3aa9124b7d2aa7212a056c4b3478f6a1891b1a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 24 Aug 2026 19:27:23 +0000 Subject: [PATCH 2/4] ci: trigger checks From 11976600d4de075331b840da8e3e055317fd3d1b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 25 Aug 2026 07:21:33 +0000 Subject: [PATCH 3/4] [Autoloop: perf-comparison] Iteration 483: add wasm_rolling_stats benchmark pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Benchmarks remaining WASM rolling/expanding statistics functions: rollingMinF64Accelerated, rollingMaxF64Accelerated, rollingVarF64Accelerated, rollingStdF64Accelerated, rollingMedianF64Accelerated, and their expanding variants — not covered by bench_wasm_agg_ops which only benchmarked sum/mean. Python counterpart uses pandas Series.rolling()/expanding() with same ops. Run: https://github.com/githubnext/tsb/actions/runs/32820317584 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- benchmarks/pandas/bench_wasm_rolling_stats.py | 64 ++++++++++++++++++ benchmarks/tsb/bench_wasm_rolling_stats.ts | 66 +++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 benchmarks/pandas/bench_wasm_rolling_stats.py create mode 100644 benchmarks/tsb/bench_wasm_rolling_stats.ts diff --git a/benchmarks/pandas/bench_wasm_rolling_stats.py b/benchmarks/pandas/bench_wasm_rolling_stats.py new file mode 100644 index 00000000..a495aed1 --- /dev/null +++ b/benchmarks/pandas/bench_wasm_rolling_stats.py @@ -0,0 +1,64 @@ +""" +Benchmark: WASM rolling/expanding stats equivalents using pandas/numpy — +Series.rolling(50).min/max/var/std/median and Series.expanding().min/max/var/std/median +on a 100k-element float64 array. + +Mirrors bench_wasm_rolling_stats.ts + +Outputs JSON: {"function": "wasm_rolling_stats", "mean_ms": ..., "iterations": ..., "total_ms": ...} +""" + +import json +import math +import time + +import numpy as np +import pandas as pd + +SIZE = 100_000 +WINDOW = 50 +MIN_PERIODS = 1 +WARMUP = 3 +ITERATIONS = 20 + +# Deterministic float64 data (same as TS counterpart) +data = np.array( + [math.sin(i * 0.001) * 100 + math.cos(i * 0.003) * 50 for i in range(SIZE)], + dtype=np.float64, +) +s = pd.Series(data) + + +def run_once() -> None: + s.rolling(WINDOW, min_periods=MIN_PERIODS).min() + s.rolling(WINDOW, min_periods=MIN_PERIODS).max() + s.rolling(WINDOW, min_periods=MIN_PERIODS).var() + s.rolling(WINDOW, min_periods=MIN_PERIODS).std() + s.rolling(WINDOW, min_periods=MIN_PERIODS).median() + s.expanding(min_periods=MIN_PERIODS).min() + s.expanding(min_periods=MIN_PERIODS).max() + s.expanding(min_periods=MIN_PERIODS).var() + s.expanding(min_periods=MIN_PERIODS).std() + s.expanding(min_periods=MIN_PERIODS).median() + + +# Warm-up +for _ in range(WARMUP): + run_once() + +# Measured iterations +t0 = time.perf_counter() +for _ in range(ITERATIONS): + run_once() +total_ms = (time.perf_counter() - t0) * 1000 + +print( + json.dumps( + { + "function": "wasm_rolling_stats", + "mean_ms": total_ms / ITERATIONS, + "iterations": ITERATIONS, + "total_ms": total_ms, + } + ) +) diff --git a/benchmarks/tsb/bench_wasm_rolling_stats.ts b/benchmarks/tsb/bench_wasm_rolling_stats.ts new file mode 100644 index 00000000..015326c3 --- /dev/null +++ b/benchmarks/tsb/bench_wasm_rolling_stats.ts @@ -0,0 +1,66 @@ +/** + * Benchmark: WASM-accelerated rolling and expanding statistics — + * rollingMinF64Accelerated, rollingMaxF64Accelerated, rollingVarF64Accelerated, + * rollingStdF64Accelerated, rollingMedianF64Accelerated, + * expandingMinF64Accelerated, expandingMaxF64Accelerated, + * expandingVarF64Accelerated, expandingStdF64Accelerated, + * expandingMedianF64Accelerated on a 100k-element float64 array. + * + * Mirrors pandas Series.rolling() and Series.expanding() with min/max/var/std/median. + * + * Outputs JSON: {"function": "wasm_rolling_stats", "mean_ms": ..., "iterations": ..., "total_ms": ...} + */ +import { + rollingMinF64Accelerated, + rollingMaxF64Accelerated, + rollingVarF64Accelerated, + rollingStdF64Accelerated, + rollingMedianF64Accelerated, + expandingMinF64Accelerated, + expandingMaxF64Accelerated, + expandingVarF64Accelerated, + expandingStdF64Accelerated, + expandingMedianF64Accelerated, +} from "../../src/wasm/index.ts"; + +const SIZE = 100_000; +const WINDOW = 50; +const MIN_PERIODS = 1; +const WARMUP = 3; +const ITERATIONS = 20; + +// Deterministic float64 data +const data = new Float64Array(SIZE); +for (let i = 0; i < SIZE; i++) { + data[i] = Math.sin(i * 0.001) * 100 + Math.cos(i * 0.003) * 50; +} + +function runOnce(): void { + rollingMinF64Accelerated(data, WINDOW, MIN_PERIODS); + rollingMaxF64Accelerated(data, WINDOW, MIN_PERIODS); + rollingVarF64Accelerated(data, WINDOW, MIN_PERIODS); + rollingStdF64Accelerated(data, WINDOW, MIN_PERIODS); + rollingMedianF64Accelerated(data, WINDOW, MIN_PERIODS); + expandingMinF64Accelerated(data, MIN_PERIODS); + expandingMaxF64Accelerated(data, MIN_PERIODS); + expandingVarF64Accelerated(data, MIN_PERIODS); + expandingStdF64Accelerated(data, MIN_PERIODS); + expandingMedianF64Accelerated(data, MIN_PERIODS); +} + +// Warm-up +for (let i = 0; i < WARMUP; i++) runOnce(); + +// Measured iterations +const t0 = performance.now(); +for (let i = 0; i < ITERATIONS; i++) runOnce(); +const total_ms = performance.now() - t0; + +console.log( + JSON.stringify({ + function: "wasm_rolling_stats", + mean_ms: total_ms / ITERATIONS, + iterations: ITERATIONS, + total_ms, + }), +); From 410d3b8b0ca7dff5f473b27292502b1a6fc4e5e0 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 25 Aug 2026 07:29:45 +0000 Subject: [PATCH 4/4] ci: trigger checks