Idler Pattern 95%

75 views
Skip to first unread message

Nick Thompson

unread,
Apr 5, 2021, 8:16:43 AM4/5/21
to libuv

Hi,

After my previous thread here, I started exploring other potential patterns for my project. I think the Idler pattern presented in the Utilities docs (http://docs.libuv.org/en/v1.x/guide/utilities.html#idler-pattern) would work well for my app, so I sketched it up briefly with my loop running with UV_RUN_DEFAULT.

I'm finding that if I call `uv_idle_start` even with a dummy callback, my app will spin up to 90-100% CPU immediately. If I never call that start, I'm at 0-1% (and of course just running the default loop). On profiling, it looks like my app spends a ton of energy going back and forth between uv__run_check and uv__io_poll.

Is there some gotcha to this pattern that I should be aware of? Or something particular I need to do to set it up correctly?

Thanks,
Nick

Reza Mahdi

unread,
Apr 5, 2021, 8:48:09 AM4/5/21
to li...@googlegroups.com
Well.... I think you are right 🧐

But consider this: when there is a idle handle in a loop, the loop don't wait for other handles. Just check them for any event. It doesn't block-and-wait. I think you have to implement some criteria to sleep the process when there is no real work to do.


--
You received this message because you are subscribed to the Google Groups "libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email to libuv+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/libuv/e9e2ed9e-477d-4386-9305-74d5333f26edn%40googlegroups.com.

Nick Thompson

unread,
Apr 5, 2021, 8:55:45 AM4/5/21
to libuv
Hm, interesting, that does make sense, thanks for the reply!

If I'm using uv_run with UV_RUN_DEFAULT, how can I get in there to sleep? And how do I determine if there's no real work to do?

Reza Mahdi

unread,
Apr 5, 2021, 9:08:13 AM4/5/21
to li...@googlegroups.com
I realized that using UV_RUN_DEFALUT is suitable for apps that doesn't care about performance too much. Just do the work 🤷

The meaning of work is a definition by your self. For example handling request can be a work, or updating some internal states of app....

I defined my work flow like this:

 1. reading callback just place the arrived data in buffer. Nothing else.
 2. When the loop ran just once, in an idle function, retrieve the buffers and sessions and handle the request.

So, Work for me is handling request, and when there is no request, there is no work to do.

I implement loop running like this:

if(sessions_count=0)
  uv_run(UV_RUN_DEFALUT);
else {
  // Start the idle handle and...
  uv_run(UV_RUN_NOWAIT);
}

I know that it is complicated 🤣, you can use prepare handle as well. Loop does waiting when there is a prepare handle in it's list.

Nick Thompson

unread,
Apr 5, 2021, 6:10:26 PM4/5/21
to libuv
Thanks for the help. I see what you're saying but I guess I'm surprised and still confused.

I took the example straight off the Basics guide (http://docs.libuv.org/en/v1.x/guide/basics.html#idling) and ran it, and I see the same thing: ~95% CPU while it runs, and that idle counter reaches 10 million in just a few seconds. That seems almost not that helpful? For example, elsewhere in the docs I found:

> An idle watcher is also useful in a GUI application. Say you are using an event loop for a file download. If the TCP socket is still being established and no other events are present your event loop will pause (block), which means your progress bar will freeze and the user will face an unresponsive application. In such a case queue up and idle watcher to keep the UI operational.

With these simple tests it seems like the idle pattern might make my GUI responsive, but at the cost of 95% CPU at all other times. Surely there's a better way?

Thanks,
Nick
Reply all
Reply to author
Forward
0 new messages