this repo has no description
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Seed each spawned process from scheduler for cheaper determinism

+22 -28
+14 -13
lib/construct/scheduler.ex
··· 56 56 end 57 57 58 58 @spec start_link(term) :: GenServer.on_start 59 - def start_link(args \\ %{}) when is_map(args) do 60 - GenServer.start_link(__MODULE__, Map.put(args, :initial_pid, self())) 59 + def start_link(seed) when is_integer(seed) do 60 + :rand.seed(:exsss, seed) 61 + scheduler_seed = random_seed() 62 + 63 + {:ok, scheduler_pid} = GenServer.start_link(__MODULE__, %{initial_pid: self(), seed: scheduler_seed}) 64 + Hobbes.Construct.SimServer.set_scheduler_pid(scheduler_pid) 65 + 66 + {:ok, scheduler_pid} 61 67 end 62 68 63 69 @spec yield(term) :: :ok ··· 143 149 GenServer.call(scheduler, {:current_time, for_pid}) 144 150 end 145 151 146 - @spec random(pid, Enum.t) :: Enum.element 147 - def random(scheduler, enumerable) do 148 - GenServer.call(scheduler, {:random, enumerable}) 149 - end 150 - 151 152 @spec configure_log_server(term, pid) :: :ok 152 153 def configure_log_server(scheduler, log_server_pid) do 153 154 GenServer.call(scheduler, {:configure_log_server, log_server_pid}) ··· 161 162 GenServer.call(scheduler, :get_log) 162 163 end 163 164 164 - def init(%{initial_pid: initial_pid} = args) do 165 - :rand.seed(:exsss, Map.get(args, :seed, {100, 101, 102})) 165 + def init(%{initial_pid: initial_pid, seed: seed}) do 166 + :rand.seed(:exsss, seed) 166 167 167 168 state = %State{ 168 169 proc_store: ProcStore.new(), ··· 206 207 def handle_call({:current_time, for_pid}, _from, %State{} = state) when is_pid(for_pid) do 207 208 # TODO: maybe we should store clock in microseconds? 208 209 {:reply, state.clock * 1000, state} 209 - end 210 - 211 - def handle_call({:random, enumerable}, _from, %State{} = state) do 212 - {:reply, Enum.random(enumerable), state} 213 210 end 214 211 215 212 def handle_call({:configure_log_server, log_server_pid}, _from, %State{} = state) do ··· 353 350 parent_pid = spawn.parent_resume.pid 354 351 355 352 scheduler_pid = self() 353 + seed = random_seed() 356 354 %Spawn{module: m, function: f, args: a} = spawn 357 355 child_pid = spawn(fn -> 358 356 Hobbes.Construct.SimServer.set_scheduler_pid(scheduler_pid) 357 + :rand.seed(:exsss, seed) 359 358 apply(m, f, a) 360 359 end) 361 360 ··· 585 584 defp log(%State{} = state, event) do 586 585 SimLog.log(state.log_server_pid, event) 587 586 end 587 + 588 + defp random_seed, do: Enum.random(1..1_000_000) 588 589 end
+4 -11
lib/construct/sim_server.ex
··· 106 106 def simulated?, do: get_scheduler_pid() != nil 107 107 108 108 @spec start_scheduler() :: {:ok, pid} 109 - def start_scheduler(seed \\ {100, 101, 102}) do 110 - {:ok, scheduler_pid} = Scheduler.start_link(%{seed: seed}) 109 + def start_scheduler(seed \\ 100) do 110 + {:ok, scheduler_pid} = Scheduler.start_link(seed) 111 + 111 112 {:ok, log_pid} = SimLog.start_link(nil) 112 113 Scheduler.configure_log_server(scheduler_pid, log_pid) 113 114 114 - set_scheduler_pid(scheduler_pid) 115 115 {:ok, scheduler_pid} 116 116 end 117 117 ··· 384 384 end 385 385 386 386 @spec deterministic_random(Enum.t) :: Enum.element 387 - def deterministic_random(enumerable) do 388 - case get_scheduler_pid() do 389 - scheduler_pid when is_pid(scheduler_pid) -> 390 - Scheduler.random(scheduler_pid, enumerable) 391 - nil -> 392 - Enum.random(enumerable) 393 - end 394 - end 387 + def deterministic_random(enumerable), do: Enum.random(enumerable) 395 388 end
+3 -2
lib/construct/sim_utils.ex
··· 28 28 29 29 hash = log_state.rolling_hash 30 30 # For readability (difficult to remember integers) 31 - hash_alpha = Base.encode32(<<hash::integer-size(32)>>, padding: false) 31 + # sha256 results in better distribution, the bytes from phash2 are too visually similar 32 + hash_alpha = :crypto.hash(:sha256, <<hash::integer-size(32)>>) |> Base.encode32(padding: false) |> String.slice(0, 8) 32 33 33 34 full_text = if opts[:full] do 34 35 """ ··· 47 48 48 49 full_text <> """ 49 50 Logged #{log_state.num_events} events with hash #{inspect(hash)} 50 - Base32 hash: #{hash_alpha}\ 51 + SHA256: #{hash_alpha}\ 51 52 """ 52 53 end 53 54
+1 -2
lib/workloads.ex
··· 65 65 {:ok, supervisor} = Task.Supervisor.start_link() 66 66 67 67 results = 68 - Enum.map(seeds, fn s -> 69 - seed = {s, 101, 102} 68 + Enum.map(seeds, fn seed -> 70 69 Task.Supervisor.async_nolink(supervisor, fn -> 71 70 run_one(seed, workloads, opts) 72 71 end)