Skip to content

Commit

Permalink
fix: Ensure aoc.run will run both parts in separate processes
Browse files Browse the repository at this point in the history
  • Loading branch information
lud committed Jan 8, 2025
1 parent 8aed26e commit 7fc90d9
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 23 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ mix aoc.run [options]
* `-y, --year <integer>` - Year of the puzzle. Defaults to today's year or custom default.
* `-d, --day <integer>` - Day of the puzzle. Defaults to today's day or custom default.
* `-p, --part <integer>` - Part of the puzzle. Defaults to both parts.
* `-b, --benchmark` - Runs the solution repeatedly for 5 seconds to print statistics about execution time. Defaults to `false`.
* `-b, --benchmark` - Runs the solution parts repeatedly for 5 seconds to print statistics about execution time. Defaults to `false`.
* `--help` - Displays this help.


Expand Down
6 changes: 3 additions & 3 deletions lib/aoc.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ defmodule AoC do
end
end

defp find_module(year, day) do
def find_module(year, day) do
with {:error, _} <- Code.ensure_loaded(Mod.module_name(year, day)),
{:error, _} <- Code.ensure_loaded(Mod.legacy_module_name(year, day)) do
{:error, :not_implemented}
Expand All @@ -27,7 +27,7 @@ defmodule AoC do
defp do_run(year, day, module, part) when is_atom(module) and part in [:part_one, :part_two] do
with {:ok, input_path} <- Input.ensure_local(year, day),
:ok <- ensure_part(module, part) do
{:ok, do_run_part(module, part, input_path)}
{:ok, call_part(module, part, input_path)}
else
{:error, :nofile} -> {:error, :not_implemented}
{:error, _} = err -> err
Expand All @@ -42,7 +42,7 @@ defmodule AoC do
end
end

defp do_run_part(module, part, input_path) do
defp call_part(module, part, input_path) do
problem = generate_problem(module, part, input_path)
apply(module, part, [problem])
end
Expand Down
1 change: 1 addition & 0 deletions lib/aoc/compute_cache.ex
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
defmodule AoC.ComputeCache do
@moduledoc false
defmacro __using__(opts) do
quote bind_quoted: binding() do
cache_vsn = Keyword.get(opts, :version, 0)
Expand Down
44 changes: 25 additions & 19 deletions lib/mix/tasks/aoc.run.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ defmodule Mix.Tasks.Aoc.Run do
default: false,
short: :b,
doc:
"Runs the solution repeatedly for 5 seconds to print statistics about execution time."
"Runs the solution parts repeatedly for 5 seconds to print statistics about execution time."
]
)

Expand Down Expand Up @@ -40,30 +40,41 @@ defmodule Mix.Tasks.Aoc.Run do
CLI.color(:yellow, to_string(day))
])

part = translate_part(part)
run_print(year, day, part)
benchmarkable_parts =
part
|> expand_parts()
|> Stream.map(fn part -> {part, run_part(year, day, part)} end)
|> Stream.map(fn {part, {usecs, result}} ->
print_result(result, usecs, year, day, part)
{part, result}
end)
|> Stream.filter(fn {_part, result} -> match?({:ok, _}, result) end)
|> Enum.map(fn {part, _} -> part end)

if options.benchmark do
benchmark(year, day, [part])
benchmark(year, day, benchmarkable_parts)
end
end

defp translate_part(n) do
defp expand_parts(n) do
case n do
1 -> :part_one
2 -> :part_two
nil -> nil
1 -> [:part_one]
2 -> [:part_two]
nil -> [:part_one, :part_two]
end
end

defp run_print(year, day, nil) do
run_print(year, day, :part_one)
run_print(year, day, :part_two)
defp run_part(year, day, part) do
{_usecs, _result} = spawn_run(year, day, part)
end

defp run_print(year, day, part) do
{usecs, result} = :timer.tc(fn -> run(year, day, part) end)
print_result(result, usecs, year, day, part)
defp spawn_run(year, day, part) do
task =
Task.async(fn ->
{_usecs, _result} = :timer.tc(fn -> run(year, day, part) end)
end)

Task.await(task, :infinity)
end

defp run(year, day, part) do
Expand Down Expand Up @@ -108,12 +119,7 @@ defmodule Mix.Tasks.Aoc.Run do
Exception.format_banner(kind, e, stack)
end

defp benchmark(year, day, [nil]) do
benchmark(year, day, [:part_one, :part_two])
end

defp benchmark(year, day, parts) do
parts = Enum.filter(parts, &match?({:ok, _}, run(year, day, &1)))
benchables = Enum.map(parts, fn part -> {part, fn -> AoC.run(year, day, part) end} end)

case benchables do
Expand Down

0 comments on commit 7fc90d9

Please sign in to comment.