Powered by AppSignal & Oban Pro

Counting numbers performantly

notebooks/counters.livemd

Counting numbers performantly

:couters module

Determine counter size

# how many numbers to manage
counter_size = 2

# one-based numbering
autorace_index = 1
toukon_index = 2

Create a counter instance

  • options
    • :atomics (default)
    • write_concurrency
my_counter = :counters.new(counter_size, [:write_concurrency])

get_state = fn ->
  %{
    autorace: :counters.get(my_counter, autorace_index),
    toukon: :counters.get(my_counter, toukon_index)
  }
end

get_state.()

Add number to counter

:counters.add(my_counter, autorace_index, 1)
:counters.add(my_counter, toukon_index, 123)
get_state.()

Subtract number from counter

:counters.sub(my_counter, autorace_index, 124)
:counters.sub(my_counter, toukon_index, 24)
get_state.()

Overwrite counter

:counters.put(my_counter, autorace_index, 0)
:counters.put(my_counter, toukon_index, 0)
get_state.()

Count large mounts of numbers

do_count = fn _ ->
  case Enum.random([:toukon, :autorace]) do
    :toukon -> :counters.add(my_counter, toukon_index, 1)
    :autorace -> :counters.add(my_counter, autorace_index, 1)
  end
end

1..100_000
|> Task.async_stream(&do_count.(&1), max_concurrency: 500)
|> Stream.run()

get_state.()

Links