Skip to content

Match compiler waiting entries directly - #15941

Merged
josevalim merged 1 commit into
elixir-lang:mainfrom
preciz:perf/compiler-match-waiting
Sep 25, 2026
Merged

josevalim merged 1 commit into
elixir-lang:mainfrom
preciz:perf/compiler-match-waiting

Conversation

@preciz

@preciz preciz commented Sep 25, 2026

Copy link
Copy Markdown
Contributor

Assisted-by: Codex:GPT-6
Assisted-by: Antigravity:Gemini 3.8 Flash

Match compiler waiting entries directly in Kernel.ParallelCompiler.

│ Match the waiting list directly instead of popping its first element through
│ a generic helper. Preserve profile output while avoiding List.pop_at/2
│ dispatch and eliminating pop-result tuple allocations.

Bench:

# Run with: ./bin/elixir bench.exs
Mix.install([:benchee])

defmodule Bench do
  def via_pop_at(waiting) do
    case List.pop_at(waiting, 0) do
      {nil, []} -> :empty
      {{kind, on, time}, rest} -> {kind, on, time, rest}
    end
  end

  def via_match(waiting) do
    case waiting do
      [] -> :empty
      [{kind, on, time} | rest] -> {kind, on, time, rest}
    end
  end
end

inputs = %{
  "empty waiting list" => [],
  "1 waiting entry" => [{:module, Foo, 123}],
  "10 waiting entries" => for(i <- 1..10, do: {:module, Foo, i})
}

Benchee.run(
  %{
    "List.pop_at/2" => &Bench.via_pop_at/1,
    "pattern match" => &Bench.via_match/1
  },
  inputs: inputs,
  time: 2,
  warmup: 1,
  memory_time: 1
)

Results:

Operating System: Linux
CPU Information: AMD Ryzen 7 8845HS w
Number of Available Cores: 16
Available memory: 54.72 GB
Elixir 1.21.0-dev
Erlang 29.0.5
JIT enabled: true

##### With input empty waiting list #####
Name                    ips        average  deviation         median         99th %
pattern match       44.17 M       22.64 ns   ±642.31%          20 ns          31 ns
List.pop_at/2       20.95 M       47.74 ns ±11058.59%          30 ns          50 ns

Comparison: 
pattern match       44.17 M
List.pop_at/2       20.95 M - 2.11x slower +25.10 ns

Memory usage statistics:

Name             Memory usage
pattern match             0 B
List.pop_at/2            24 B - ∞ x memory usage +24 B

**All measurements for memory usage were the same**

##### With input 1 waiting entry #####
Name                    ips        average  deviation         median         99th %
pattern match       33.06 M       30.25 ns   ±759.47%          30 ns          40 ns
List.pop_at/2       20.30 M       49.26 ns  ±8897.95%          40 ns          60 ns

Comparison: 
pattern match       33.06 M
List.pop_at/2       20.30 M - 1.63x slower +19.01 ns

Memory usage statistics:

Name             Memory usage
pattern match            40 B
List.pop_at/2            64 B - 1.60x memory usage +24 B

**All measurements for memory usage were the same**

##### With input 10 waiting entries #####
Name                    ips        average  deviation         median         99th %
pattern match       32.02 M       31.23 ns  ±2635.49%          30 ns          41 ns
List.pop_at/2       23.18 M       43.14 ns  ±4781.26%          40 ns          60 ns

Comparison: 
pattern match       32.02 M
List.pop_at/2       23.18 M - 1.38x slower +11.91 ns

Memory usage statistics:

Name             Memory usage
pattern match            40 B
List.pop_at/2            64 B - 1.60x memory usage +24 B

**All measurements for memory usage were the same**

Match the waiting list directly instead of popping its first element through a generic helper. Preserve profile output while eliminating nonempty pop-result tuples.

Assisted-by: Codex:GPT-6
@josevalim
josevalim merged commit 029258e into elixir-lang:main Sep 25, 2026
15 checks passed
@josevalim

Copy link
Copy Markdown
Member

💚 💙 💜 💛 ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants