I just want to say I am incredibly blown away by Elixir’s time precision. Despite it being a multi-threaded system, the timing is quite incredible.
If you run something like this:
defmodule My.TestGenServer do
use GenServer
#==================
# START LINK
#==================
def start_link(initial_state) do
GenServer.start_link(__MODULE__, initial_state, name: __MODULE__)
end
#==================
# INIT FUNCTION
#==================
def init(initial_state) do
#init tasks
initial_state = %{}
initial_state = Map.put(initial_state, :date_time, NaiveDateTime.utc_now());
schedule_work() # Schedule the first work
{:ok, initial_state}
end
#==================
# HANDLE INFO
#==================
def handle_info(:work, state) do
# Perform your periodic task here
{:ok, state} = perform_work(:work, state) # must save the state back again in here
schedule_work()
{:noreply, state}
end
#==================
# WORK TASK
#==================
defp perform_work(:work, state) do
#IO.puts("Performing periodic work...")
#check delta time
datetime_1 = Map.get(state, :date_time)
datetime = NaiveDateTime.utc_now()
diff = NaiveDateTime.diff(datetime, datetime_1, :millisecond)
state = Map.put(state, :date_time, datetime)
IO.puts("MILLISECONDS DT " <> to_string(diff));
{:ok, state}
end
#==================
# SCHEDULE TASK
#==================
defp schedule_work do
# Schedule the next work in milliseconds
Process.send_after(self(), :work, 3)
end
end
You can get incredible reliability on the performance. The output tends to be on my system 1 milliscond greater than the scheduling on average. Eg. If you schedule 3 ms, you may get mostly 4 ms (but this is still amazing for such small time increments). if you schedule 16 ms you may get 17 ms on average.
But it is still quite amazing. Chat GPT says:
Elixir’s accuracy with timers primarily stems from its underlying architecture and the features of the Erlang virtual machine (BEAM) on which it runs. Here are some reasons why Elixir is particularly suited for accurate timing and scheduling:
Erlang/BEAM Scheduler
- The BEAM virtual machine uses a preemptive scheduling system, allowing it to manage lightweight processes efficiently. This design helps in accurately executing scheduled tasks without significant delays.
The only way I know you can get millisecond accurate timers on Windows is with special multimedia libraries. Android and iOS are impossible as far as I recall last I tried.
It just makes me wonder why we can’t specify smaller increments than 1 ms. Can we say 16.6 ms (ie 60 increments per second)?
Any thoughts on the 1 ms lag that is so consistent it seems? Is that perhaps the 1 ms to do the work each loop and reschedule?
Thanks for any thoughts.