-module(starfuzz@benchmark). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/starfuzz/benchmark.gleam"). -export([now/0, new/0, add_algorithm/3, add_cases/2, with_iterations/2, run/1]). -export_type(['case'/0, algorithm/0, benchmark_result/0, benchmark_builder/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " A module providing performance benchmarking capabilities.\n" " Compares execution speeds of different similarity algorithms over a suite of test cases\n" " with target-independent millisecond timing.\n" ). -type 'case'() :: {'case', binary(), binary(), binary()}. -type algorithm() :: {algorithm, binary(), fun((binary(), binary()) -> float())}. -type benchmark_result() :: {benchmark_result, binary(), binary(), integer(), integer()}. -type benchmark_builder() :: {benchmark_builder, list(algorithm()), list('case'()), integer()}. -file("src/starfuzz/benchmark.gleam", 11). ?DOC( " Returns the current system epoch time in milliseconds.\n" " Implemented via native Erlang and JavaScript FFI.\n" ). -spec now() -> integer(). now() -> starfuzz_erl_ffi:now(). -file("src/starfuzz/benchmark.gleam", 50). ?DOC(" Creates a new BenchmarkBuilder with 1000 default iterations and no algorithms or cases.\n"). -spec new() -> benchmark_builder(). new() -> {benchmark_builder, [], [], 1000}. -file("src/starfuzz/benchmark.gleam", 59). ?DOC(" Adds a named similarity algorithm to the suite.\n"). -spec add_algorithm( benchmark_builder(), binary(), fun((binary(), binary()) -> float()) ) -> benchmark_builder(). add_algorithm(Builder, Name, Run) -> {benchmark_builder, [{algorithm, Name, Run} | erlang:element(2, Builder)], erlang:element(3, Builder), erlang:element(4, Builder)}. -file("src/starfuzz/benchmark.gleam", 64). ?DOC(" Adds a list of test cases to the suite.\n"). -spec add_cases(benchmark_builder(), list('case'())) -> benchmark_builder(). add_cases(Builder, Cases) -> {benchmark_builder, erlang:element(2, Builder), lists:append(erlang:element(3, Builder), Cases), erlang:element(4, Builder)}. -file("src/starfuzz/benchmark.gleam", 69). ?DOC(" Configures the number of iterations to execute for each test.\n"). -spec with_iterations(benchmark_builder(), integer()) -> benchmark_builder(). with_iterations(Builder, Iterations) -> {benchmark_builder, erlang:element(2, Builder), erlang:element(3, Builder), Iterations}. -file("src/starfuzz/benchmark.gleam", 73). -spec run_iterations( fun((binary(), binary()) -> float()), binary(), binary(), integer() ) -> nil. run_iterations(Run_fn, Left, Right, Count) -> case Count =< 0 of true -> nil; false -> _ = Run_fn(Left, Right), run_iterations(Run_fn, Left, Right, Count - 1) end. -file("src/starfuzz/benchmark.gleam", 84). ?DOC(" Runs the benchmark suite and returns the aggregated timing results.\n"). -spec run(benchmark_builder()) -> list(benchmark_result()). run(Builder) -> gleam@list:flat_map( erlang:element(3, Builder), fun(Case_item) -> gleam@list:map( erlang:element(2, Builder), fun(Alg) -> Start = starfuzz_erl_ffi:now(), run_iterations( erlang:element(3, Alg), erlang:element(3, Case_item), erlang:element(4, Case_item), erlang:element(4, Builder) ), End = starfuzz_erl_ffi:now(), {benchmark_result, erlang:element(2, Alg), erlang:element(2, Case_item), erlang:element(4, Builder), End - Start} end ) end ).