-module(lightspeed@ops@performance_harness). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/lightspeed/ops/performance_harness.gleam"). -export([pinned_profile/0, default_suite/0, default_budget/0, run_suite_with/2, run_suite/0, evaluate_budget/2, budget_failures/1, workload_label/1, budget_label/1, report_signature/1]). -export_type([workload/0, profile/0, scenario/0, scenario_report/0, report/0, budget/0, budget_result/0, sample/0, crud_state/0, stream_state/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(" Deterministic benchmark harness for M11 performance parity gate.\n"). -type workload() :: counter | crud_table | stream_heavy_list | form_heavy_flow. -type profile() :: {profile, binary(), integer(), integer(), integer()}. -type scenario() :: {scenario, workload(), integer(), integer()}. -type scenario_report() :: {scenario_report, workload(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer(), integer()}. -type report() :: {report, profile(), list(scenario_report())}. -type budget() :: {budget, workload(), integer(), integer(), integer(), integer()}. -type budget_result() :: {budget_result, workload(), boolean(), binary()}. -type sample() :: {sample, integer(), integer(), integer(), integer()}. -type crud_state() :: {crud_state, integer(), lightspeed@stream:stream()}. -type stream_state() :: {stream_state, integer(), lightspeed@stream:stream()}. -file("src/lightspeed/ops/performance_harness.gleam", 84). ?DOC(" Deterministic pinned profile for M11 reproducibility.\n"). -spec pinned_profile() -> profile(). pinned_profile() -> {profile, <<"beam-sim-pinned-v1"/utf8>>, 100, 100, 100}. -file("src/lightspeed/ops/performance_harness.gleam", 95). ?DOC( " Default benchmark suite for M11:\n" " counter, CRUD table, stream-heavy list, and form-heavy flow.\n" ). -spec default_suite() -> list(scenario()). default_suite() -> [{scenario, counter, 64, 48}, {scenario, crud_table, 24, 60}, {scenario, stream_heavy_list, 20, 72}, {scenario, form_heavy_flow, 40, 40}]. -file("src/lightspeed/ops/performance_harness.gleam", 109). ?DOC(" Default parity budget for M11 gate checks.\n"). -spec default_budget() -> list(budget()). default_budget() -> [{budget, counter, 80, 400, 40, 400}, {budget, crud_table, 120, 1200, 20, 1200}, {budget, stream_heavy_list, 180, 1400, 16, 1800}, {budget, form_heavy_flow, 100, 500, 25, 700}]. -file("src/lightspeed/ops/performance_harness.gleam", 919). -spec nth(list(integer()), integer()) -> integer(). nth(Values, Index) -> case Values of [] -> 0; [Head | Rest] -> case Index =< 0 of true -> Head; false -> nth(Rest, Index - 1) end end. -file("src/lightspeed/ops/performance_harness.gleam", 999). -spec clamp(integer(), integer(), integer()) -> integer(). clamp(Minimum, Maximum, Value) -> case Value < Minimum of true -> Minimum; false -> case Value > Maximum of true -> Maximum; false -> Value end end. -file("src/lightspeed/ops/performance_harness.gleam", 989). -spec ceil_div(integer(), integer()) -> integer(). ceil_div(Numerator, Denominator) -> case Denominator =< 0 of true -> 0; false -> Adjusted = (Numerator + Denominator) - 1, case Denominator of 0 -> 0; Gleam@denominator -> Adjusted div Gleam@denominator end end. -file("src/lightspeed/ops/performance_harness.gleam", 908). -spec insert_sorted(list(integer()), integer()) -> list(integer()). insert_sorted(Values, Value) -> case Values of [] -> [Value]; [Head | Rest] -> case Value =< Head of true -> [Value, Head | Rest]; false -> [Head | insert_sorted(Rest, Value)] end end. -file("src/lightspeed/ops/performance_harness.gleam", 901). -spec sort_ints(list(integer()), list(integer())) -> list(integer()). sort_ints(Values, Sorted) -> case Values of [] -> Sorted; [Value | Rest] -> sort_ints(Rest, insert_sorted(Sorted, Value)) end. -file("src/lightspeed/ops/performance_harness.gleam", 889). -spec percentile(list(integer()), integer()) -> integer(). percentile(Values, Pct) -> case sort_ints(Values, []) of [] -> 0; Sorted -> N = erlang:length(Sorted), Rank = ceil_div(N * Pct, 100), Index = clamp(0, N - 1, Rank - 1), nth(Sorted, Index) end. -file("src/lightspeed/ops/performance_harness.gleam", 1017). -spec max_int(integer(), integer()) -> integer(). max_int(Left, Right) -> case Left >= Right of true -> Left; false -> Right end. -file("src/lightspeed/ops/performance_harness.gleam", 982). -spec divide_safe(integer(), integer()) -> integer(). divide_safe(Numerator, Denominator) -> case Denominator =< 0 of true -> 0; false -> case Denominator of 0 -> 0; Gleam@denominator -> Numerator div Gleam@denominator end end. -file("src/lightspeed/ops/performance_harness.gleam", 951). -spec peak_memory_units(list(sample()), integer()) -> integer(). peak_memory_units(Samples, Peak) -> case Samples of [] -> Peak; [Sample | Rest] -> peak_memory_units(Rest, max_int(Peak, erlang:element(5, Sample))) end. -file("src/lightspeed/ops/performance_harness.gleam", 944). -spec sum_patch_ops(list(sample()), integer()) -> integer(). sum_patch_ops(Samples, Total) -> case Samples of [] -> Total; [Sample | Rest] -> sum_patch_ops(Rest, Total + erlang:element(4, Sample)) end. -file("src/lightspeed/ops/performance_harness.gleam", 937). -spec sum_payload_bytes(list(sample()), integer()) -> integer(). sum_payload_bytes(Samples, Total) -> case Samples of [] -> Total; [Sample | Rest] -> sum_payload_bytes(Rest, Total + erlang:element(3, Sample)) end. -file("src/lightspeed/ops/performance_harness.gleam", 930). -spec sum_latencies(list(sample()), integer()) -> integer(). sum_latencies(Samples, Total) -> case Samples of [] -> Total; [Sample | Rest] -> sum_latencies(Rest, Total + erlang:element(2, Sample)) end. -file("src/lightspeed/ops/performance_harness.gleam", 882). -spec latencies(list(sample()), list(integer())) -> list(integer()). latencies(Samples, Latencies_rev) -> case Samples of [] -> lists:reverse(Latencies_rev); [Sample | Rest] -> latencies(Rest, [erlang:element(2, Sample) | Latencies_rev]) end. -file("src/lightspeed/ops/performance_harness.gleam", 775). -spec latency_ms( profile(), workload(), integer(), integer(), integer(), integer() ) -> integer(). latency_ms( Profile, Workload, Payload_bytes, Patch_ops, Memory_units, Complexity_hint ) -> Base = case Workload of counter -> 2; crud_table -> 5; stream_heavy_list -> 6; form_heavy_flow -> 4 end, Payload_cost = divide_safe( Payload_bytes, max_int(18, erlang:element(4, Profile) div 5) ), Patch_cost = Patch_ops * 2, Memory_cost = divide_safe( Memory_units, max_int(20, erlang:element(5, Profile) div 4) ), Complexity_cost = Complexity_hint rem 3, Cpu_discount = divide_safe(erlang:element(3, Profile), 250), max_int( 1, ((((Base + Payload_cost) + Patch_cost) + Memory_cost) + Complexity_cost) - Cpu_discount ). -file("src/lightspeed/ops/performance_harness.gleam", 748). -spec sample_from_patches( profile(), workload(), list(lightspeed@diff:patch()), integer(), integer() ) -> sample(). sample_from_patches(Profile, Workload, Patches, Memory_units, Complexity_hint) -> Patch_ops = erlang:length(Patches), Payload_bytes = case Patch_ops =:= 0 of true -> 0; false -> string:length(lightspeed@diff:encode_stream(Patches)) end, {sample, latency_ms( Profile, Workload, Payload_bytes, Patch_ops, Memory_units, Complexity_hint ), Payload_bytes, Patch_ops, Memory_units}. -file("src/lightspeed/ops/performance_harness.gleam", 694). -spec pending_count_loop( lightspeed@form_compat:runtime(), list(binary()), integer() ) -> integer(). pending_count_loop(Runtime, Names, Count) -> case Names of [] -> Count; [Name | Rest] -> case lightspeed@form_compat:has_pending(Runtime, Name) of true -> pending_count_loop(Runtime, Rest, Count + 1); false -> pending_count_loop(Runtime, Rest, Count) end end. -file("src/lightspeed/ops/performance_harness.gleam", 689). -spec pending_count(lightspeed@form_compat:runtime()) -> integer(). pending_count(Runtime) -> Names = [<<"title"/utf8>>, <<"search"/utf8>>, <<"status"/utf8>>, <<"priority"/utf8>>], pending_count_loop(Runtime, Names, 0). -file("src/lightspeed/ops/performance_harness.gleam", 671). -spec form_patch(binary(), binary(), lightspeed@form:form_data(), integer()) -> lightspeed@diff:patch(). form_patch(Kind, Input, Payload, Step) -> {update_segments, <<"#form"/utf8>>, <<"form-flow/v1"/utf8>>, [lightspeed@diff:slot(<<"kind"/utf8>>, Kind), lightspeed@diff:slot(<<"input"/utf8>>, Input), lightspeed@diff:slot( <<"fields"/utf8>>, erlang:integer_to_binary( erlang:length(lightspeed@form:fields(Payload)) ) ), lightspeed@diff:slot( <<"step"/utf8>>, erlang:integer_to_binary(Step) )]}. -file("src/lightspeed/ops/performance_harness.gleam", 647). -spec patches_from_dispatches( list(lightspeed@form_compat:dispatch()), integer(), list(lightspeed@diff:patch()) ) -> list(lightspeed@diff:patch()). patches_from_dispatches(Dispatches, Step, Patches_rev) -> case Dispatches of [] -> lists:reverse(Patches_rev); [Dispatch | Rest] -> case Dispatch of {dispatch_change, Input, Payload} -> patches_from_dispatches( Rest, Step, [form_patch(<<"change"/utf8>>, Input, Payload, Step) | Patches_rev] ); {dispatch_submit, Payload@1} -> patches_from_dispatches( Rest, Step, [form_patch( <<"submit"/utf8>>, <<"form"/utf8>>, Payload@1, Step ) | Patches_rev] ); _ -> patches_from_dispatches(Rest, Step, Patches_rev) end end. -file("src/lightspeed/ops/performance_harness.gleam", 586). -spec form_step( lightspeed@form_compat:runtime(), integer(), integer(), integer() ) -> {lightspeed@form_compat:runtime(), list(lightspeed@form_compat:dispatch())}. form_step(Runtime, Session_index, Step, At_ms) -> case Step rem 6 of 1 -> {Next, Dispatch} = lightspeed@form_compat:change( Runtime, <<"title"/utf8>>, <<<<<<"title=task+"/utf8, (erlang:integer_to_binary(Session_index))/binary>>/binary, "-"/utf8>>/binary, (erlang:integer_to_binary(Step))/binary>>, At_ms ), {Next, [Dispatch]}; 2 -> {Next@1, Dispatch@1} = lightspeed@form_compat:change( Runtime, <<"search"/utf8>>, <<"search=query+"/utf8, (erlang:integer_to_binary(Step))/binary>>, At_ms ), {Next@1, [Dispatch@1]}; 3 -> {Next@2, Dispatch@2} = lightspeed@form_compat:change( Runtime, <<"priority"/utf8>>, <<"priority="/utf8, (erlang:integer_to_binary(Step rem 4))/binary>>, At_ms ), {Next@2, [Dispatch@2]}; 4 -> {Next@3, Dispatch@3} = lightspeed@form_compat:blur( Runtime, <<"status"/utf8>>, At_ms ), {Next@3, [Dispatch@3]}; 5 -> {Next@4, Dispatches} = lightspeed@form_compat:tick( Runtime, At_ms + 100 ), {Next@4, Dispatches}; _ -> {Next@5, Dispatch@4} = lightspeed@form_compat:submit( Runtime, <<"title=save&status=open"/utf8>>, At_ms ), {Next@5, [Dispatch@4]} end. -file("src/lightspeed/ops/performance_harness.gleam", 557). -spec form_loop( profile(), lightspeed@form_compat:runtime(), integer(), integer(), integer(), list(sample()) ) -> list(sample()). form_loop(Profile, Runtime, Remaining, Session_index, Step, Samples_rev) -> case Remaining =< 0 of true -> lists:reverse(Samples_rev); false -> Now_ms = Step * 17, {Next_runtime, Dispatches} = form_step( Runtime, Session_index, Step, Now_ms ), Patches = patches_from_dispatches(Dispatches, Step, []), Memory = pending_count(Next_runtime) + erlang:length( lightspeed@form:fields( lightspeed@form:parse_payload( <<"title=one&status=open"/utf8>> ) ) ), Sample = sample_from_patches( Profile, form_heavy_flow, Patches, Memory, Step ), form_loop( Profile, Next_runtime, Remaining - 1, Session_index, Step + 1, [Sample | Samples_rev] ) end. -file("src/lightspeed/ops/performance_harness.gleam", 535). -spec form_heavy_workload(profile(), integer(), integer()) -> list(sample()). form_heavy_workload(Profile, Events_per_session, Session_index) -> Runtime = lightspeed@form_compat:new( [{input_config, <<"title"/utf8>>, immediate}, {input_config, <<"search"/utf8>>, {debounce, 80}}, {input_config, <<"status"/utf8>>, debounce_blur}, {input_config, <<"priority"/utf8>>, {throttle, 60}}] ), form_loop(Profile, Runtime, Events_per_session, Session_index, 1, []). -file("src/lightspeed/ops/performance_harness.gleam", 515). -spec stream_batch(integer(), integer(), list(lightspeed@stream:stream_item())) -> list(lightspeed@stream:stream_item()). stream_batch(Next_id, Count, Entries_rev) -> case Count =< 0 of true -> lists:reverse(Entries_rev); false -> Id = <<"item-"/utf8, (erlang:integer_to_binary(Next_id))/binary>>, stream_batch( Next_id + 1, Count - 1, [lightspeed@stream:item( Id, <<<<<<<<"
  • >/binary, "\">B"/utf8>>/binary, (erlang:integer_to_binary(Next_id))/binary>>/binary, "
  • "/utf8>> ) | Entries_rev] ) end. -file("src/lightspeed/ops/performance_harness.gleam", 462). -spec stream_step(stream_state(), integer()) -> {stream_state(), list(lightspeed@diff:patch()), integer()}. stream_step(State, Step) -> Current_entries = lightspeed@stream:entries(erlang:element(3, State)), case (Step rem 10) =:= 0 of true -> Batch = stream_batch(erlang:element(2, State), 8, []), {Rows, Patches} = lightspeed@stream:stream( erlang:element(3, State), Batch, begin _pipe = lightspeed@stream:options(), _pipe@1 = lightspeed@stream:with_reset(_pipe, true), lightspeed@stream:with_limit(_pipe@1, -120) end ), Memory = (erlang:length(lightspeed@stream:entries(Rows)) * 4) + (erlang:length( Patches ) * 2), {{stream_state, erlang:element(2, State) + 8, Rows}, Patches, Memory}; false -> case {(Step rem 3) =:= 0, Current_entries} of {true, [Head | _]} -> {Rows@1, Patches@1} = lightspeed@stream:stream_delete( erlang:element(3, State), erlang:element(2, Head) ), Memory@1 = (erlang:length(lightspeed@stream:entries(Rows@1)) * 4) + (erlang:length(Patches@1) * 2), {{stream_state, erlang:element(2, State), Rows@1}, Patches@1, Memory@1}; {_, _} -> At = case (Step rem 2) =:= 0 of true -> 0; false -> -1 end, Id = <<"item-"/utf8, (erlang:integer_to_binary(erlang:element(2, State)))/binary>>, Entry = lightspeed@stream:item( Id, <<<<<<<<"
  • >/binary, "\">"/utf8>>/binary, (erlang:integer_to_binary(Step))/binary>>/binary, "
  • "/utf8>> ), {Rows@2, Patches@2} = lightspeed@stream:stream_insert( erlang:element(3, State), Entry, At, {some, -120} ), Memory@2 = (erlang:length(lightspeed@stream:entries(Rows@2)) * 4) + (erlang:length(Patches@2) * 2), {{stream_state, erlang:element(2, State) + 1, Rows@2}, Patches@2, Memory@2} end end. -file("src/lightspeed/ops/performance_harness.gleam", 435). -spec stream_loop( profile(), stream_state(), integer(), integer(), list(sample()) ) -> list(sample()). stream_loop(Profile, State, Remaining, Step, Samples_rev) -> case Remaining =< 0 of true -> lists:reverse(Samples_rev); false -> {Next_state, Patches, Memory_units} = stream_step(State, Step), Sample = sample_from_patches( Profile, stream_heavy_list, Patches, Memory_units, Step + 2 ), stream_loop( Profile, Next_state, Remaining - 1, Step + 1, [Sample | Samples_rev] ) end. -file("src/lightspeed/ops/performance_harness.gleam", 422). -spec stream_heavy_workload(profile(), integer(), integer()) -> list(sample()). stream_heavy_workload(Profile, Events_per_session, Session_index) -> Seed = {stream_state, 1, lightspeed@stream:new( <<"#stream-"/utf8, (erlang:integer_to_binary(Session_index))/binary>> )}, stream_loop(Profile, Seed, Events_per_session, 1, []). -file("src/lightspeed/ops/performance_harness.gleam", 391). -spec crud_step(crud_state(), integer()) -> {crud_state(), list(lightspeed@diff:patch()), integer()}. crud_step(State, Step) -> Limit = {some, -60}, case (Step rem 7) =:= 0 of true -> Delete_id = <<"row-"/utf8, (erlang:integer_to_binary( max_int(1, erlang:element(2, State) - 9) ))/binary>>, {Rows, Patches} = lightspeed@stream:stream_delete( erlang:element(3, State), Delete_id ), Memory = (erlang:length(lightspeed@stream:entries(Rows)) * 3) + 16, {{crud_state, erlang:element(2, State), Rows}, Patches, Memory}; false -> Id = <<"row-"/utf8, (erlang:integer_to_binary(erlang:element(2, State)))/binary>>, Row = lightspeed@stream:item( Id, <<<<<<<<""/utf8, Id/binary>>/binary, "Status "/utf8>>/binary, (erlang:integer_to_binary(Step rem 5))/binary>>/binary, ""/utf8>> ), {Rows@1, Patches@1} = lightspeed@stream:stream_insert( erlang:element(3, State), Row, -1, Limit ), Memory@1 = (erlang:length(lightspeed@stream:entries(Rows@1)) * 3) + 16, {{crud_state, erlang:element(2, State) + 1, Rows@1}, Patches@1, Memory@1} end. -file("src/lightspeed/ops/performance_harness.gleam", 370). -spec crud_loop(profile(), crud_state(), integer(), integer(), list(sample())) -> list(sample()). crud_loop(Profile, State, Remaining, Step, Samples_rev) -> case Remaining =< 0 of true -> lists:reverse(Samples_rev); false -> {Next_state, Patches, Memory_units} = crud_step(State, Step), Sample = sample_from_patches( Profile, crud_table, Patches, Memory_units, Step ), crud_loop( Profile, Next_state, Remaining - 1, Step + 1, [Sample | Samples_rev] ) end. -file("src/lightspeed/ops/performance_harness.gleam", 357). -spec crud_workload(profile(), integer(), integer()) -> list(sample()). crud_workload(Profile, Events_per_session, Session_index) -> Seed = {crud_state, 1, lightspeed@stream:new( <<"#crud-"/utf8, (erlang:integer_to_binary(Session_index))/binary>> )}, crud_loop(Profile, Seed, Events_per_session, 1, []). -file("src/lightspeed/ops/performance_harness.gleam", 967). -spec send( lightspeed@agent@session:session(), binary(), lightspeed@agent@session:inbox_event() ) -> lightspeed@agent@session:session(). send(State, Owner, Event) -> lightspeed@agent@session:handle(State, {inbox_message, Owner, Event}). -file("src/lightspeed/ops/performance_harness.gleam", 959). -spec ack_first_pending(lightspeed@agent@session:session(), binary()) -> lightspeed@agent@session:session(). ack_first_pending(State, Owner) -> case lightspeed@agent@session:oldest_pending_patch(State) of none -> State; {some, Patch} -> send(State, Owner, {ack, lightspeed@agent@session:patch_ref(Patch)}) end. -file("src/lightspeed/ops/performance_harness.gleam", 709). -spec sample_from_session_patch( profile(), workload(), lightspeed@agent@session:session() ) -> sample(). sample_from_session_patch(Profile, Workload, State) -> case lightspeed@agent@session:oldest_pending_patch(State) of none -> {sample, latency_ms(Profile, Workload, 0, 0, 0, 1), 0, 0, 0}; {some, Patch} -> Encoded = lightspeed@diff:encode( lightspeed@agent@session:patch(Patch) ), Payload_bytes = string:length(Encoded), Patch_ops = 1, Memory_units = lightspeed@agent@session:pending_patch_count(State) + divide_safe( lightspeed@agent@session:telemetry_count(State), 2 ), {sample, latency_ms( Profile, Workload, Payload_bytes, Patch_ops, Memory_units, lightspeed@agent@session:counter(State) ), Payload_bytes, Patch_ops, Memory_units} end. -file("src/lightspeed/ops/performance_harness.gleam", 335). -spec counter_loop( profile(), lightspeed@agent@session:session(), binary(), integer(), integer(), list(sample()) ) -> list(sample()). counter_loop(Profile, State, Owner, Remaining, Step, Samples_rev) -> case Remaining =< 0 of true -> lists:reverse(Samples_rev); false -> Updated = send(State, Owner, increment), Sample = sample_from_session_patch(Profile, counter, Updated), Next = ack_first_pending(Updated, Owner), counter_loop( Profile, Next, Owner, Remaining - 1, Step + 1, [Sample | Samples_rev] ) end. -file("src/lightspeed/ops/performance_harness.gleam", 311). -spec counter_workload(profile(), integer(), integer()) -> list(sample()). counter_workload(Profile, Events_per_session, Session_index) -> Session_id = <<"bench-counter-"/utf8, (erlang:integer_to_binary(Session_index))/binary>>, Owner = <<"proc-counter-"/utf8, (erlang:integer_to_binary(Session_index))/binary>>, Route = <<"/counter/"/utf8, (erlang:integer_to_binary(Session_index))/binary>>, State = lightspeed@agent@session:start(Session_id, Owner, rehydrate, 0, 120), Connected = send( State, Owner, {connect, Route, <<"csrf-"/utf8, Session_id/binary>>, 0} ), Connected@1 = ack_first_pending(Connected, Owner), counter_loop(Profile, Connected@1, Owner, Events_per_session, 1, []). -file("src/lightspeed/ops/performance_harness.gleam", 295). -spec run_workload(profile(), workload(), integer(), integer()) -> list(sample()). run_workload(Profile, Workload, Events_per_session, Session_index) -> case Workload of counter -> counter_workload(Profile, Events_per_session, Session_index); crud_table -> crud_workload(Profile, Events_per_session, Session_index); stream_heavy_list -> stream_heavy_workload(Profile, Events_per_session, Session_index); form_heavy_flow -> form_heavy_workload(Profile, Events_per_session, Session_index) end. -file("src/lightspeed/ops/performance_harness.gleam", 975). -spec prepend_samples(list(sample()), list(sample())) -> list(sample()). prepend_samples(Values, Acc) -> case Values of [] -> Acc; [Value | Rest] -> prepend_samples(Rest, [Value | Acc]) end. -file("src/lightspeed/ops/performance_harness.gleam", 270). -spec run_sessions( profile(), workload(), integer(), integer(), integer(), list(sample()) ) -> list(sample()). run_sessions( Profile, Workload, Session_count, Events_per_session, Index, Samples_rev ) -> case Index > Session_count of true -> lists:reverse(Samples_rev); false -> run_sessions( Profile, Workload, Session_count, Events_per_session, Index + 1, prepend_samples( run_workload(Profile, Workload, Events_per_session, Index), Samples_rev ) ) end. -file("src/lightspeed/ops/performance_harness.gleam", 1010). -spec clamp_positive(integer(), integer()) -> integer(). clamp_positive(Value, Fallback) -> case Value =< 0 of true -> Fallback; false -> Value end. -file("src/lightspeed/ops/performance_harness.gleam", 237). -spec run_scenario(profile(), scenario()) -> scenario_report(). run_scenario(Profile, Scenario) -> Sessions = clamp_positive(erlang:element(3, Scenario), 1), Per_session = clamp_positive(erlang:element(4, Scenario), 1), Samples = run_sessions( Profile, erlang:element(2, Scenario), Sessions, Per_session, 1, [] ), Latencies = latencies(Samples, []), Total_events = erlang:length(Samples), Total_latency_ms = sum_latencies(Samples, 0), Total_payload_bytes = sum_payload_bytes(Samples, 0), Total_patch_ops = sum_patch_ops(Samples, 0), Peak_memory_units_per_session = peak_memory_units(Samples, 0), Avg_payload_bytes = divide_safe(Total_payload_bytes, Total_events), Avg_patch_ops = divide_safe(Total_patch_ops, Total_events), Throughput = divide_safe(Total_events * 1000, max_int(Total_latency_ms, 1)), {scenario_report, erlang:element(2, Scenario), Sessions, Per_session, Total_events, percentile(Latencies, 50), percentile(Latencies, 95), Total_payload_bytes, Avg_payload_bytes, Total_patch_ops, Avg_patch_ops, Peak_memory_units_per_session, Peak_memory_units_per_session * Sessions, Throughput}. -file("src/lightspeed/ops/performance_harness.gleam", 222). -spec run_scenarios(profile(), list(scenario()), list(scenario_report())) -> list(scenario_report()). run_scenarios(Profile, Suite, Reports_rev) -> case Suite of [] -> lists:reverse(Reports_rev); [Scenario | Rest] -> run_scenarios( Profile, Rest, [run_scenario(Profile, Scenario) | Reports_rev] ) end. -file("src/lightspeed/ops/performance_harness.gleam", 148). ?DOC(" Run benchmarks for one profile and scenario list.\n"). -spec run_suite_with(profile(), list(scenario())) -> report(). run_suite_with(Profile, Suite) -> {report, Profile, run_scenarios(Profile, Suite, [])}. -file("src/lightspeed/ops/performance_harness.gleam", 143). ?DOC(" Run benchmarks with pinned profile and default suite.\n"). -spec run_suite() -> report(). run_suite() -> run_suite_with(pinned_profile(), default_suite()). -file("src/lightspeed/ops/performance_harness.gleam", 1043). -spec bool_to_string(boolean()) -> binary(). bool_to_string(Value) -> case Value of true -> <<"true"/utf8>>; false -> <<"false"/utf8>> end. -file("src/lightspeed/ops/performance_harness.gleam", 868). -spec find_scenario(list(scenario_report()), workload()) -> gleam@option:option(scenario_report()). find_scenario(Scenarios, Workload) -> case Scenarios of [] -> none; [Scenario | Rest] -> case erlang:element(2, Scenario) =:= Workload of true -> {some, Scenario}; false -> find_scenario(Rest, Workload) end end. -file("src/lightspeed/ops/performance_harness.gleam", 823). -spec evaluate_one_budget(list(scenario_report()), budget()) -> budget_result(). evaluate_one_budget(Scenarios, Budget) -> case find_scenario(Scenarios, erlang:element(2, Budget)) of none -> {budget_result, erlang:element(2, Budget), false, <<"missing_scenario"/utf8>>}; {some, Report} -> Passed_latency = erlang:element(7, Report) =< erlang:element( 3, Budget ), Passed_payload = erlang:element(9, Report) =< erlang:element( 4, Budget ), Passed_throughput = erlang:element(14, Report) >= erlang:element( 5, Budget ), Passed_memory = erlang:element(12, Report) =< erlang:element( 6, Budget ), Passed = ((Passed_latency andalso Passed_payload) andalso Passed_throughput) andalso Passed_memory, {budget_result, erlang:element(2, Budget), Passed, case Passed of true -> <<"within_budget"/utf8>>; false -> <<<<<<<<<<<<<<"latency="/utf8, (bool_to_string( Passed_latency ))/binary>>/binary, ",payload="/utf8>>/binary, (bool_to_string(Passed_payload))/binary>>/binary, ",throughput="/utf8>>/binary, (bool_to_string(Passed_throughput))/binary>>/binary, ",memory="/utf8>>/binary, (bool_to_string(Passed_memory))/binary>> end} end. -file("src/lightspeed/ops/performance_harness.gleam", 808). -spec evaluate_budget_loop( list(scenario_report()), list(budget()), list(budget_result()) ) -> list(budget_result()). evaluate_budget_loop(Scenarios, Budgets, Results_rev) -> case Budgets of [] -> lists:reverse(Results_rev); [Budget | Rest] -> evaluate_budget_loop( Scenarios, Rest, [evaluate_one_budget(Scenarios, Budget) | Results_rev] ) end. -file("src/lightspeed/ops/performance_harness.gleam", 153). ?DOC(" Evaluate one report against one budget list.\n"). -spec evaluate_budget(report(), list(budget())) -> list(budget_result()). evaluate_budget(Report, Budgets) -> evaluate_budget_loop(erlang:element(3, Report), Budgets, []). -file("src/lightspeed/ops/performance_harness.gleam", 161). ?DOC(" Count failing budget checks.\n"). -spec budget_failures(list(budget_result())) -> integer(). budget_failures(Results) -> case Results of [] -> 0; [{budget_result, _, Passed, _} | Rest] -> case Passed of true -> budget_failures(Rest); false -> 1 + budget_failures(Rest) end end. -file("src/lightspeed/ops/performance_harness.gleam", 173). ?DOC(" Stable workload label.\n"). -spec workload_label(workload()) -> binary(). workload_label(Workload) -> case Workload of counter -> <<"counter"/utf8>>; crud_table -> <<"crud_table"/utf8>>; stream_heavy_list -> <<"stream_heavy_list"/utf8>>; form_heavy_flow -> <<"form_heavy_flow"/utf8>> end. -file("src/lightspeed/ops/performance_harness.gleam", 183). ?DOC(" Stable pass/fail label.\n"). -spec budget_label(budget_result()) -> binary(). budget_label(Result) -> case erlang:element(3, Result) of true -> <<"pass"/utf8>>; false -> <<"fail"/utf8>> end. -file("src/lightspeed/ops/performance_harness.gleam", 1031). -spec join_with_loop(list(binary()), binary(), binary()) -> binary(). join_with_loop(Values, Separator, Acc) -> case Values of [] -> Acc; [Entry | Rest] -> join_with_loop( Rest, Separator, <<<>/binary, Entry/binary>> ) end. -file("src/lightspeed/ops/performance_harness.gleam", 1024). -spec join_with(list(binary()), binary()) -> binary(). join_with(Values, Separator) -> case Values of [] -> <<""/utf8>>; [First | Rest] -> join_with_loop(Rest, Separator, First) end. -file("src/lightspeed/ops/performance_harness.gleam", 191). ?DOC(" Stable report signature suitable for CI artifact comparisons.\n"). -spec report_signature(report()) -> binary(). report_signature(Report) -> Profile = <<<<<<<<<<<<(erlang:element(2, erlang:element(2, Report)))/binary, ":cpu="/utf8>>/binary, (erlang:integer_to_binary( erlang:element(3, erlang:element(2, Report)) ))/binary>>/binary, ":io="/utf8>>/binary, (erlang:integer_to_binary( erlang:element(4, erlang:element(2, Report)) ))/binary>>/binary, ":mem="/utf8>>/binary, (erlang:integer_to_binary(erlang:element(5, erlang:element(2, Report))))/binary>>, Scenario_signature = begin _pipe = erlang:element(3, Report), _pipe@1 = gleam@list:map( _pipe, fun(Scenario) -> <<<<<<<<<<<<<<<<<<<<<<<<(workload_label( erlang:element( 2, Scenario ) ))/binary, ":p50="/utf8>>/binary, (erlang:integer_to_binary( erlang:element( 6, Scenario ) ))/binary>>/binary, ":p95="/utf8>>/binary, (erlang:integer_to_binary( erlang:element( 7, Scenario ) ))/binary>>/binary, ":avg_payload="/utf8>>/binary, (erlang:integer_to_binary( erlang:element(9, Scenario) ))/binary>>/binary, ":avg_ops="/utf8>>/binary, (erlang:integer_to_binary( erlang:element(11, Scenario) ))/binary>>/binary, ":mem="/utf8>>/binary, (erlang:integer_to_binary( erlang:element(12, Scenario) ))/binary>>/binary, ":throughput="/utf8>>/binary, (erlang:integer_to_binary(erlang:element(14, Scenario)))/binary>> end ), join_with(_pipe@1, <<";"/utf8>>) end, <<<>/binary, Scenario_signature/binary>>.