Skip to content

Avoid repeated conversions when shifting Calendar.ISO times - #15925

Merged
josevalim merged 1 commit into
elixir-lang:mainfrom
preciz:perf/calendar-joffe-8
Sep 22, 2026
Merged

josevalim merged 1 commit into
elixir-lang:mainfrom
preciz:perf/calendar-joffe-8

Conversation

@preciz

@preciz preciz commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Assisted-by: Codex:GPT-6

~1.5x faster, uses less memory.

Replace duration options and reduction with tuple dispatch. Fold whole
seconds into the time tuple and apply microseconds in a single shift,
preserving precision and a fast path for zero shifts.

Bench:

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

path = "lib/elixir/lib/calendar/iso.ex"

for {ref, module} <- [{"main", Old}, {"HEAD", New}] do
  {source, 0} = System.cmd("git", ["show", "#{ref}:#{path}"], cd: __DIR__)

  source
  |> String.replace("defmodule Calendar.ISO do", "defmodule #{inspect(module)} do")
  |> Code.compile_string(path)
end

inputs = %{
  "zero duration" => [],
  "seconds only" => [second: 86_401],
  "microseconds only" => [microsecond: {500_001, 6}],
  "seconds and microseconds" => [second: 86_401, microsecond: {500_001, 6}]
}

Benchee.run(
  %{
    "main" => &Old.shift_time(23, 59, 59, {120_000, 3}, &1),
    "HEAD" => &New.shift_time(23, 59, 59, {120_000, 3}, &1)
  },
  inputs: Map.new(inputs, fn {name, units} -> {name, Duration.new!(units)} end),
  pre_check: :all_same,
  warmup: 1,
  time: 3,
  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

Benchmark suite executing with the following configuration:
warmup: 1 s
time: 3 s
memory time: 1 s
reduction time: 0 ns
parallel: 1
inputs: microseconds only, seconds and microseconds, seconds only, zero duration
Estimated total run time: 40 s
Excluding outliers: false

##### With input microseconds only #####
Name           ips        average  deviation         median         99th %
HEAD        9.91 M      100.89 ns  ±5244.69%          90 ns         131 ns
main        7.92 M      126.30 ns  ±3650.24%         101 ns         201 ns

Comparison: 
HEAD        9.91 M
main        7.92 M - 1.25x slower +25.40 ns

Memory usage statistics:

Name    Memory usage
HEAD           288 B
main           368 B - 1.28x memory usage +80 B

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

##### With input seconds and microseconds #####
Name           ips        average  deviation         median         99th %
HEAD        9.33 M      107.20 ns  ±5579.27%          90 ns         140 ns
main        4.53 M      220.86 ns  ±3458.13%         190 ns         310 ns

Comparison: 
HEAD        9.33 M
main        4.53 M - 2.06x slower +113.67 ns

Memory usage statistics:

Name    Memory usage
HEAD           288 B
main           640 B - 2.22x memory usage +352 B

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

##### With input seconds only #####
Name           ips        average  deviation         median         99th %
HEAD        8.82 M      113.42 ns  ±5136.35%          90 ns         180 ns
main        7.13 M      140.33 ns  ±4783.83%         110 ns         220 ns

Comparison: 
HEAD        8.82 M
main        7.13 M - 1.24x slower +26.91 ns

Memory usage statistics:

Name    Memory usage
HEAD           312 B
main           392 B - 1.26x memory usage +80 B

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

##### With input zero duration #####
Name           ips        average  deviation         median         99th %
HEAD       29.05 M       34.43 ns  ±4411.93%          30 ns          41 ns
main       18.05 M       55.41 ns  ±1479.18%          50 ns          81 ns

Comparison: 
HEAD       29.05 M
main       18.05 M - 1.61x slower +20.98 ns

Memory usage statistics:

Name    Memory usage
HEAD            40 B
main           120 B - 3.00x memory usage +80 B

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

Replace duration options and reduction with tuple dispatch. Fold whole
seconds into the time tuple and apply microseconds in a single shift,
preserving precision and a fast path for zero shifts.

Assisted-by: Codex:GPT-6
@josevalim
josevalim merged commit 22c2150 into elixir-lang:main Sep 22, 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