Ex4pmEngine.Bench.Topology (ex4pm v26.9.9)

Copy Markdown View Source

Real BEAM-native benchmark harness comparing distributed-engine topologies for process discovery (directly-follows graph, DFG), under a virtual-cost model (Ex4pmEngine.Bench.VirtualCost: compute/store/send operation counts) rather than wall-clock time.

A toy event log is a list of {case_id, activity, timestamp} tuples. Discovery computes the DFG: for each case, sort its events by timestamp, then count {activity_a, activity_b} directly-follows edge frequencies across all cases. The DFG is %{ {a, b} => frequency }.

Two real topologies are implemented:

  • :centralized — a single process holds the whole log, sorts each case, and builds the DFG directly. No inter-process communication.
  • :edge — the log is partitioned across N real BEAM processes (one Task per simulated node), each computes a local partial DFG over its own shard of cases, then sends its partial DFG back to the coordinator, which merges them by summing edge frequencies. This exercises real message passing (Task.async/Task.await, which is a real send/receive round-trip), not just a sequential map/reduce in one process.

Both topologies are asserted (by the test suite) to produce the same final merged DFG for the same input log — the correctness invariant this harness exists to check before its virtual-cost numbers are trusted.

Summary

Functions

Runs discovery in the :centralized topology: one process does everything.

Runs discovery in the :edge topology: the log is partitioned across node_count real BEAM processes (Tasks), each computes a local DFG over its shard, and results are merged by the coordinator.

Generates a real synthetic toy event log with case_count cases, each following one of a small fixed set of activity sequences (with case-specific timestamps), for use as harness input in benchmarks/tests.

Types

dfg()

@type dfg() :: %{optional({String.t(), String.t()}) => pos_integer()}

event()

@type event() :: {case_id :: term(), activity :: String.t(), timestamp :: integer()}

Functions

run_centralized(events)

@spec run_centralized([event()]) :: {dfg(), Ex4pmEngine.Bench.VirtualCost.t()}

Runs discovery in the :centralized topology: one process does everything.

Returns {dfg, virtual_cost}.

run_edge(events, node_count)

@spec run_edge([event()], pos_integer()) :: {dfg(), Ex4pmEngine.Bench.VirtualCost.t()}

Runs discovery in the :edge topology: the log is partitioned across node_count real BEAM processes (Tasks), each computes a local DFG over its shard, and results are merged by the coordinator.

Returns {dfg, virtual_cost} where virtual_cost is the coordinator's own cost merged with every worker's real reported cost — i.e. the true total cost of the distributed run, not just the coordinator's local view.

synthetic_log(case_count)

@spec synthetic_log(pos_integer()) :: [event()]

Generates a real synthetic toy event log with case_count cases, each following one of a small fixed set of activity sequences (with case-specific timestamps), for use as harness input in benchmarks/tests.