Skip to content

Commit

Permalink
Small performance improvement for cold boot BEAM
Browse files Browse the repository at this point in the history
I'm running my tests on AMD 24 cores/6.6.51-1-lts kernel.

```
Erlang/OTP 27 [erts-15.0] [source] [64-bit] [smp:128:24] [ds:128:24:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.17.1) - press Ctrl+C to exit (type h() ENTER for help)
```

My colleagues on macs could not ever reproduce the cold boot
slowdown, one person with Intel linux could.

This change consists of two minor improvements.

1. Use `MapSet.new/1` rather than `Enum.into/2`

Apparently, on some architectures at least, this makes
a significant difference on cold VM boot:

(clean `iex` required each time)

```
iex(1)> :timer.tc(fn -> MapSet.new([%{}]) end)
{5, MapSet.new([%{}])}
```

```
iex(1)> :timer.tc(fn -> Enum.into([%{}], MapSet.new()) end)
{7931, MapSet.new([%{}])}

iex(2)> :timer.tc(fn -> Enum.into([%{}], MapSet.new()) end)
{12, MapSet.new([%{}])}
```

This change is functionally equivalent, but in code
utilizing ConCache locks, it does cause occasional timeouts
with acquire limited to 500ms, while running tests -
especially if the seed happens to cause lock congestion
very early on after task startup.

I can also mitigate the issue locally, by warming up ConCache in
`test_helper.exs` by doing a loop of enough isolated calls
to cover all the partitions, but upstream change feels much better.

Even if the _real_ issue is still elsewhere, the pure gain
is still worth it I hope.

2. Ensure that when running tests where `ConCache` as a dependency,
`ConCache.Lock.Resource` is loaded before the lock pool is started.
In some cases, dynamic module resolution caused `Resource.new`
to even add up 300ms of latency 🫣. I'm not sure if there's a cleaner
way of making sure that module is loaded when the application starts?

Thanks for looking.
  • Loading branch information
aerosol committed Sep 17, 2024
1 parent 09b98ed commit 2a60565
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/con_cache/lock/monitors.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ defmodule ConCache.Lock.Monitors do
%{
count: 1,
monitor: Process.monitor(pid),
lock_instances: Enum.into([lock_instance], MapSet.new())
lock_instances: MapSet.new([lock_instance])
}

{:ok, process_info} ->
Expand Down
2 changes: 2 additions & 0 deletions lib/con_cache/lock_supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ defmodule ConCache.LockSupervisor do
end

def start_link(n_partitions) do
true = Code.ensure_loaded?(ConCache.Lock.Resource)

Supervisor.start_link(
Enum.map(
1..n_partitions,
Expand Down

0 comments on commit 2a60565

Please sign in to comment.