diff --git a/benchmarks/pandas/bench_assign.py b/benchmarks/pandas/bench_assign.py new file mode 100644 index 00000000..104729bb --- /dev/null +++ b/benchmarks/pandas/bench_assign.py @@ -0,0 +1,28 @@ +"""Benchmark: DataFrame.assign — add computed columns to a 100k-row DataFrame""" +import json, time +import numpy as np +import pandas as pd + +ROWS = 100_000 +WARMUP = 3 +ITERATIONS = 10 + +df = pd.DataFrame({ + "a": np.arange(ROWS, dtype=float), + "b": np.arange(ROWS, dtype=float) * 2, +}) + +for _ in range(WARMUP): + df.assign(c=lambda d: d["a"] + d["b"]) + +start = time.perf_counter() +for _ in range(ITERATIONS): + df.assign(c=lambda d: d["a"] + d["b"]) +total = (time.perf_counter() - start) * 1000 + +print(json.dumps({ + "function": "assign", + "mean_ms": total / ITERATIONS, + "iterations": ITERATIONS, + "total_ms": total, +})) diff --git a/benchmarks/pandas/bench_filter_labels.py b/benchmarks/pandas/bench_filter_labels.py new file mode 100644 index 00000000..cf0d8c37 --- /dev/null +++ b/benchmarks/pandas/bench_filter_labels.py @@ -0,0 +1,31 @@ +"""Benchmark: DataFrame.filter by items on 100k-row DataFrame""" +import json, time +import numpy as np +import pandas as pd + +ROWS = 100_000 +WARMUP = 3 +ITERATIONS = 10 + +df = pd.DataFrame({ + "alpha": np.arange(ROWS, dtype=float), + "beta": np.arange(ROWS, dtype=float) * 2, + "gamma": np.arange(ROWS, dtype=float) * 3, + "delta": np.arange(ROWS, dtype=float) * 4, + "epsilon": np.arange(ROWS, dtype=float) * 5, +}) + +for _ in range(WARMUP): + df.filter(items=["alpha", "gamma", "epsilon"]) + +start = time.perf_counter() +for _ in range(ITERATIONS): + df.filter(items=["alpha", "gamma", "epsilon"]) +total = (time.perf_counter() - start) * 1000 + +print(json.dumps({ + "function": "filter_labels", + "mean_ms": total / ITERATIONS, + "iterations": ITERATIONS, + "total_ms": total, +})) diff --git a/benchmarks/pandas/bench_transform_agg.py b/benchmarks/pandas/bench_transform_agg.py new file mode 100644 index 00000000..b1f48d83 --- /dev/null +++ b/benchmarks/pandas/bench_transform_agg.py @@ -0,0 +1,27 @@ +"""Benchmark: Series.transform — transform a 100k-element Series""" +import json, time +import numpy as np +import pandas as pd + +ROWS = 100_000 +WARMUP = 3 +ITERATIONS = 10 + +data = (np.arange(ROWS) % 500) + 1.0 +idx = np.arange(ROWS) % 500 +s = pd.Series(data, index=idx) + +for _ in range(WARMUP): + s.transform("mean") + +start = time.perf_counter() +for _ in range(ITERATIONS): + s.transform("mean") +total = (time.perf_counter() - start) * 1000 + +print(json.dumps({ + "function": "transform_agg", + "mean_ms": total / ITERATIONS, + "iterations": ITERATIONS, + "total_ms": total, +})) diff --git a/benchmarks/pandas/bench_truncate.py b/benchmarks/pandas/bench_truncate.py new file mode 100644 index 00000000..dc968929 --- /dev/null +++ b/benchmarks/pandas/bench_truncate.py @@ -0,0 +1,26 @@ +"""Benchmark: truncate on 100k-element Series""" +import json, time +import numpy as np +import pandas as pd + +ROWS = 100_000 +WARMUP = 3 +ITERATIONS = 10 + +data = np.arange(ROWS) * 0.5 +s = pd.Series(data, index=np.arange(ROWS)) + +for _ in range(WARMUP): + s.truncate(before=10_000, after=90_000) + +start = time.perf_counter() +for _ in range(ITERATIONS): + s.truncate(before=10_000, after=90_000) +total = (time.perf_counter() - start) * 1000 + +print(json.dumps({ + "function": "truncate", + "mean_ms": total / ITERATIONS, + "iterations": ITERATIONS, + "total_ms": total, +})) diff --git a/benchmarks/tsb/bench_assign.ts b/benchmarks/tsb/bench_assign.ts new file mode 100644 index 00000000..6de46c6e --- /dev/null +++ b/benchmarks/tsb/bench_assign.ts @@ -0,0 +1,36 @@ +/** + * Benchmark: dataFrameAssign — add computed columns to a 100k-row DataFrame + */ +import { DataFrame, dataFrameAssign } from "../../src/index.js"; + +const ROWS = 100_000; +const WARMUP = 3; +const ITERATIONS = 10; + +const df = DataFrame.fromColumns({ + a: Float64Array.from({ length: ROWS }, (_, i) => i), + b: Float64Array.from({ length: ROWS }, (_, i) => i * 2), +}); + +for (let i = 0; i < WARMUP; i++) { + dataFrameAssign(df, { + c: (d: DataFrame) => d.col("a").add(d.col("b")), + }); +} + +const start = performance.now(); +for (let i = 0; i < ITERATIONS; i++) { + dataFrameAssign(df, { + c: (d: DataFrame) => d.col("a").add(d.col("b")), + }); +} +const total = performance.now() - start; + +console.log( + JSON.stringify({ + function: "assign", + mean_ms: total / ITERATIONS, + iterations: ITERATIONS, + total_ms: total, + }), +); diff --git a/benchmarks/tsb/bench_filter_labels.ts b/benchmarks/tsb/bench_filter_labels.ts new file mode 100644 index 00000000..757e2176 --- /dev/null +++ b/benchmarks/tsb/bench_filter_labels.ts @@ -0,0 +1,36 @@ +/** + * Benchmark: filterDataFrame by items and regex on 100k-row DataFrame + */ +import { DataFrame, filterDataFrame } from "../../src/index.js"; + +const ROWS = 100_000; +const WARMUP = 3; +const ITERATIONS = 10; + +const df = DataFrame.fromColumns({ + alpha: Float64Array.from({ length: ROWS }, (_, i) => i), + beta: Float64Array.from({ length: ROWS }, (_, i) => i * 2), + gamma: Float64Array.from({ length: ROWS }, (_, i) => i * 3), + delta: Float64Array.from({ length: ROWS }, (_, i) => i * 4), + epsilon: Float64Array.from({ length: ROWS }, (_, i) => i * 5), +}); + +// Filter by items +for (let i = 0; i < WARMUP; i++) { + filterDataFrame(df, { items: ["alpha", "gamma", "epsilon"] }); +} + +const start = performance.now(); +for (let i = 0; i < ITERATIONS; i++) { + filterDataFrame(df, { items: ["alpha", "gamma", "epsilon"] }); +} +const total = performance.now() - start; + +console.log( + JSON.stringify({ + function: "filter_labels", + mean_ms: total / ITERATIONS, + iterations: ITERATIONS, + total_ms: total, + }), +); diff --git a/benchmarks/tsb/bench_transform_agg.ts b/benchmarks/tsb/bench_transform_agg.ts new file mode 100644 index 00000000..8d06ceba --- /dev/null +++ b/benchmarks/tsb/bench_transform_agg.ts @@ -0,0 +1,30 @@ +/** + * Benchmark: seriesTransform — transform a 100k-element Series + */ +import { Series, seriesTransform } from "../../src/index.js"; + +const ROWS = 100_000; +const WARMUP = 3; +const ITERATIONS = 10; + +const data = Float64Array.from({ length: ROWS }, (_, i) => (i % 500) + 1); +const s = new Series({ data, index: Array.from({ length: ROWS }, (_, i) => i % 500) }); + +for (let i = 0; i < WARMUP; i++) { + seriesTransform(s, "mean"); +} + +const start = performance.now(); +for (let i = 0; i < ITERATIONS; i++) { + seriesTransform(s, "mean"); +} +const total = performance.now() - start; + +console.log( + JSON.stringify({ + function: "transform_agg", + mean_ms: total / ITERATIONS, + iterations: ITERATIONS, + total_ms: total, + }), +); diff --git a/benchmarks/tsb/bench_truncate.ts b/benchmarks/tsb/bench_truncate.ts new file mode 100644 index 00000000..5d8e70ca --- /dev/null +++ b/benchmarks/tsb/bench_truncate.ts @@ -0,0 +1,30 @@ +/** + * Benchmark: truncateSeries on 100k-element Series + */ +import { Series, truncateSeries } from "../../src/index.js"; + +const ROWS = 100_000; +const WARMUP = 3; +const ITERATIONS = 10; + +const data = Float64Array.from({ length: ROWS }, (_, i) => i * 0.5); +const s = new Series({ data, index: Array.from({ length: ROWS }, (_, i) => i) }); + +for (let i = 0; i < WARMUP; i++) { + truncateSeries(s, 10_000, 90_000); +} + +const start = performance.now(); +for (let i = 0; i < ITERATIONS; i++) { + truncateSeries(s, 10_000, 90_000); +} +const total = performance.now() - start; + +console.log( + JSON.stringify({ + function: "truncate", + mean_ms: total / ITERATIONS, + iterations: ITERATIONS, + total_ms: total, + }), +);