Is there a way to set the priority of a genserver process to :high?
On a more general note, a periodic genserver (scheduled via Process.send_after/3 sending a message to self()) generally executes the handle_info callback on time, but at times will be scheduled after 2x/3x the desired period. Are there any ways to mitigate this (apart from setting the priority, which might not even be effective?)
Is it possible that your GenServer has other messages in it’s mail box? The “problem” with send_after/3 is that it will only send the message at that time. Meaning if your process already has messages, it will deal with those ones first. Which may seem like it is not running your message until some time later.
I have never actually had the need to adjust a processes priority, but I do remember people advising against this. A quick search does not yield specifics on it though. Maybe someone else can fill in the blanks here.
At the end of the day, if you have a particularily busy system, the only things you can really do is to either optimize the slow part(s) of your application, start distributing the workload, or just get a larger machine to run the work.
Is it possible that your GenServer has other messages in it’s mail box? The “problem” with send_after/3 is that it will only send the message at that time. Meaning if your process already has messages, it will deal with those ones first. Which may seem like it is not running your message until some time later.
No, this is not the case. The worker only receives one kind of the message, from itself, to schedule more work (which itself is done async). So even if the mailbox is full with the same kind of message, I’d imagine its because the worker is not getting scheduled.
I have never actually had the need to adjust a processes priority, but I do remember people advising against this. A quick search does not yield specifics on it though. Maybe someone else can fill in the blanks here.
Yeah I read this, but only for :max, which is used by the Erlang runtime.
Are you sure that the GenServer isn’t blocked on something else leaving it unable to respond in a timely manner? Lots of functions are a disguised GenServer.call/3 which is a blocking, selective receive with a default timeout of 5000 ms.
If you’re scheduling it to run every 2 seconds but it’s actually taking 4 to 6 seconds then either the super is very overloaded or there’s something else going on. Can you show the code you’re using?
def init(state) do
schedule_work(state.execution_period)
{:ok, state}
end
def handle_info(:work, state) do
schedule_work(state.execution_period)
spawn_link(fn -> WorkerModule.work(state.data) end)
{:noreply, %{state | last_execution_time_in_msec: System.monotonic_time(:millisecond)}}
end
defp schedule_work(interval) do
Process.send_after(self(), :work, interval)
end
@peerreynders I don’t think I am calling any blocking functions.
Hmm, I have a similar scheduling server in Kiq.Periodic.Scheduler and it schedules reliably for days down to the millisecond.
Is there a chance the worker you are spawning is crashing? If so it would be restarted infrequently enough that the supervisor would keep restarting it. The crash + restart + delay could be enough to put it off schedule.
@idi527 I am not sure Is there any way to find out(maybe through the observer?)
@sorentwo That is very interesting that it works for you. When mine works, it is mostly reliable (drift of around ~1ms per invocation). I am pretty sure it’s not crashing. I am using :sys.trace/2 to print state and see last_execution_time_in_msec and I don’t see crashes.
Using spawn_link makes the asynchronous code that you are trying to execute effect the genserver. If the spawned process dies so does the genserver and maybe this is something that you don’t want. Have you tried to use only spawn? Also if this solves the problem but you still want to monitor the spawned processes you can monitor them with something like Process.monitor. What do you think?
Quick update, I don’t seem to notice this issue anymore. I don’t think I changed anything, so this is a little surprising. I will update the thread if I notice it again.