Re: About describe doubt for libev release ..

2020-03-22 Thread Marc Lehmann
On Sun, Mar 22, 2020 at 12:56:16PM +0800, CandyMi <869646...@qq.com> wrote:
> I have the same opinion about Linux aio and io_uring. The performance of aio 
> is not as good and problematic as described, but the use of io_uring may be 
> limited by the version of the Linux kernel and it makes me hesitant.
> 
> There may be very few people who follow up on Linux 4.x / 5.x aggressively, 
> that is to say, there will be very few people who actually use it! And I also 
> have to maintain the old 2.6.32 kernel project).

Actually, I would assume most people are now on a 4.x kernel, but of
course, select and poll keep being supported and lubev will fall back to
these if required.

> The following code is my implementation of the IO watcher wrapper. The only 
> difference is: "the IO watcher passed to the core IO init method may have 
> called the core IO stop multiple times (object reuse). Such behavior is to 
> reduce the frequent creation or destruction of IO watcher."

This got rather garbled, but I have one comment:

> core_io_stop(core_loop *loop, core_io *io){
>   if (io-events || io-fd){

If you want to check whether a watche ris active (strated), you could use
ev_is_active(w).

Your current if has the disadvantage of not stopping all acive watchers,
as 0 is a valid value for both fd and events.

>   io-fd = io-events = 0x0;

Also, after stopping, you can reuse the watche rmemory in any way you like,
but you then cannot start it again without calling ev_io_init.

> It is worth mentioning the use of the ev_timer_again method: "The consequence 
> of modifying timer- repeat is that it will cause the min-heap to be 
> adjusted every time. Will frequent use have a certain impact or even worse 
> performance?", Because The implementation of ev_timer_again is this (v4.25):

While other data structures are possible, and I vaguely plan some minor
optimisations, when you use ev_timer_again, libev of course has to adjust the
heap to reflect the new reality. ev_timer_again is typically faster than a
stop/start though, which is why it exists.

Depending on your needs, you may be able to further optimize timers by not
updating them at all on every change (e.g. for network timeouts, letting
them expire and reschedule to the real timeout in the callback), or by
creating your own data structure, e.g. if you have a lot of timers with
the same timeout, you can put them into a linked list and only create a
real timer for the next timer in that list, adding new timers to th end
and so on.

> Recently, I was watching the code of libeio. When will libeio be ready to 
> release the official version?

I can call it an official version right now and create a CVS tag if that
helps you. The main blocking issue is probably the lack of documentation,
and some doubts on whether this is really the right API.

And of course, libeio might profit most from io_uring.

In terms of stability, libeio is pretty much stable and in maintenance for
a decade now.

-- 
The choice of a   Deliantra, the free code+content MORPG
  -==- _GNU_  http://www.deliantra.net
  ==-- _   generation
  ---==---(_)__  __   __  Marc Lehmann
  --==---/ / _ \/ // /\ \/ /  schm...@schmorp.de
  -=/_/_//_/\_,_/ /_/\_\

___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev


Re: About describe doubt for libev release ..

2020-03-22 Thread CandyMi
"While other data structures are possible and I vaguely plan some minor 
optimisations"


 I'm very happy to hear what you said! Because every optimization of 
Timer makes it easy for developers to use without having to hold hands in some 
cases (I wrote a lot of code for this).


 I mentioned in my email last year: "About the choice of the data 
structure of the timer watcher". But I didn't get a reply, I want to 
communicate with you about this possibility here.


 In general, we will use the following code to reflect when a network 
connection should be closed:


 static void timer_cb(...) {


  ev_io_stop(...);


 }




 static void io_cb(...) {


  ev_timer_stop(...);


 }


 static void listet_socket (int sock, int events, int timeout, int 
repeats, void* data) {


  io-data = data;
  ev_io_init(io, sock, io_cb, READ or write);
  ev_io_start(loop, io);


  timer-data = data;
  ev_timer_init(timer, timer_cb, timeout, repeats);
  ev_timer_start(loop, io);


  


 }


 Of course, there is a simpler "ev_once" available. But when managing 
more than 100,000 network connections, the overhead of the data structure 
itself already occupies a very high user space.


 My current solution is the same as what you said: "Once you need to stop 
the timer, mark it in timer- data!", Wait for the real timeout before 
calling ev_timer_stop to stop it.


 The modified code looks like this:


 static void timer_cb(...) {


  if (timer-data-closed == 1) {
   ev_timer_again(...); // only need to stop timer.
   return ;
  }


  ev_timer_again(...);


  ev_io_stop(...);


  ...


 }


 static void io_cb(...) {


  // ev_timer_stop(...); before


  timer-data-closed = 1; // now


  ..


 }


 But obviously, this makes the code we write gradually less and less 
readable.


 Can libev provide a "painless" way for developers to use 
"ev_timer_start" at will without having to consider using "trick" to simplify 
the complexity of the algorithm?


 I have observed that a timer called "Timer-wheel" is provided in the 
Linux kernel, and its algorithm complexity is currently constant. This may be a 
good reference.


 Have you considered optimizing by changing the data structure, or do you 
still have other "killer" ways to optimize? Will this affect the stability?


___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev


Re: libev-4.31 has just been released

2020-03-22 Thread Marc Lehmann
On Sun, Mar 22, 2020 at 05:57:02PM -0400, Benjamin Mahler 
 wrote:
> Thanks Marc, do you have any broader comments on the implications of
> iouring for libev? It looks like iouring is finally bringing async system
> calls (not just async io) to Linux.

As far as I have been told, you will even be able to upload (ebpf)
programs into the kernel, and you can already do chained requests of
sorts (open/read/close for example).

I haven't seen direct signs of bringing async system calls into iouring
though, but that might be because I am simply uninformed, and concentrate
on what libev needs first. It's also not really a concern for either
libeio or libev.

> Will libeio have an iouring backend that doesn't use a thread pool and
> instead hands the io off to the kernel with io_uring?

I don't think the threadpool can be avoided, as some things will have to
be done in userspace (e.g. eio_readdir), but yes, as a very heavy libeio
user I'd be very keen on getting many requests into iouring, stat(x),
open/close, read/write are pretty high in my personal priority list, and it's
certainly possible to do this in smaller steps.

This will be useful even if io_uring turns out to be slower than epoll
for I/O notifications - which is an ongoing concern, due to the less
streamlined API (e.g. io_uring requires a hash lookup to find watchers
whereas epoll can just use an array lookup, and this is worsened by
io_uring requiring kernel interactions per event notification and not just
per watcher, as epoll does). But even if slightly slower, it might still
become the default backend simply because it avoids so many design issues
that epoll suffers from.

I currently can't see a reasonably easy way of sharing the io_uring
between libev and libeio, so they will likely use a separate io_uring
instance anyway.

But while I am confident on the plans for libeio, I am less confident
on the timeframe - it might be very quick, or it might take a long
time. Important will be my experiences with io_uring in libev w.r.t.
speed and queuing behaviour - libev already had some major design changes
internally to accomodate io_uring (as documented in fd_reify), which can
bring some instability to the codebase.

-- 
The choice of a   Deliantra, the free code+content MORPG
  -==- _GNU_  http://www.deliantra.net
  ==-- _   generation
  ---==---(_)__  __   __  Marc Lehmann
  --==---/ / _ \/ // /\ \/ /  schm...@schmorp.de
  -=/_/_//_/\_,_/ /_/\_\

___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev


Re: About describe doubt for libev release ..

2020-03-22 Thread Marc Lehmann
On Mon, Mar 23, 2020 at 02:44:58AM +0800, CandyMi <869646...@qq.com> wrote:
> "While other data structures are possible and I vaguely plan some minor 
> optimisations"
> 
>  I'm very happy to hear what you said! Because every optimization of 
> Timer makes it easy for developers to use without having to hold hands in 
> some cases (I wrote a lot of code for this).
>  I mentioned in my email last year: "About the choice of the data 
> structure of the timer watcher". But I didn't get a reply, I want to 
> communicate with you about this possibility here.

First of all, your mails arrive very garbled here, as if you mailer sent
html instead of text - could you work on improving that= That makes
reading and understanding your mails unnecessarily hard.

As for optimisations, there is a limit to that - libev cannot know how
your timers are used, and trying ti find out will slow it down so much
that it isn't worth optimizing for many important cases. The biggest
savings are to be done on the application side.

>  Of course, there is a simpler "ev_once" available. But when managing 
> more than 100,000 network connections, the overhead of the data structure 
> itself already occupies a very high user space.

That's a very good example - ev_once does a (costly) malloc each time, and
there is no good way aorund that (it could speed up the allocation, but it
will have to allocate). Real savings can be done on the application side,
by arranging its own data structures in a way that avoids extra memory
allocastions altogether.

>  My current solution is the same as what you said: "Once you need to 
> stop the timer, mark it in timer- data!", Wait for the real timeout 
> before calling ev_timer_stop to stop it.

That's not what I said (in fact, I personally do not use the data field
very often, and wish there was a nice way to get rid of it, but there
isn't, unless you compile libev yourself).

What I meant is more clearly explained in
http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#Be_smart_about_timeouts,
part 3 (Let the timer time out, but then re-arm it as required.) - basically,
if you have an inactivity timeout of, say, 60 seconds, you can have a timer
that runs at least every 60 seconds, and then calculates the real timeout.
That way, when there is activity (typically much more often than once per
minute), you only need to do a single assignment instead of rearming the
timer.

And that needs to be done on the application side.

If you have many sockets with identical timeouts, you can be much more
efficient. For example, you could have a list sorted by activity and a single
timer for all connections.

And if you don't need super-exact timeout, but have lots of connections, you
could have a timer that runs every n seconds and reaps connections.

A generic event library can't know this and/or do this for you.

I did play with the thought of having many more watcher types, such as a
watcher type that has it's own container in which all timers have the same
timeout, which could be used for that, but that was when I was under the
influence of Perl's Event module API, and in the end, the more minimal
libevent way of doing things won over.

Most importantly, libev tries to allow applications to do all of this
themselves without forcing them into a particular style, which isd what I
learned from other event loops which aren't as generic.

>   if (timer-data-closed == 1) {
>ev_timer_again(...); // only need to stop timer.
>return ;
>   }
> 
>   timer-data-closed = 1; // now

That doesn't seem like an advantage - if you know the timer is no longer
needed, it should be cheaper to stop it directly and be done with it.

>  Can libev provide a "painless" way for developers to use 
> "ev_timer_start" at will without having to consider using "trick" to simplify 
> the complexity of the algorithm?

I think it already does, to the extent possible. I think your specific
trick is actually malking it worse, but I could be convinced on the
opposite by a benchmark :) But I suspect the conditions under which it
could be better would have to be very specific.

The reason why it is likely worse is that a lot of timers increase the
timer heap size, and effectively the same work has to be done as when
calling ev_io_stop, plus extra work because the heap is larger and the
operations likely have worse cache locality.

>  I have observed that a timer called "Timer-wheel" is provided in the 
> Linux kernel, and its algorithm complexity is currently constant. This may be 
> a good reference.

I know how the kernel does it - however, while it suits the kernel, it
cannot emulate libev timers, and just because it might be O(1) on some
operations does not mean it is faster than a good heap.

And most importantly, you can't have both a timer wheel (which requires your
application to design aorund it) and a timer implementation that just works
for every application (as in libev), i.e. your goal of being generic and easy
to use directly 

Re: libev-4.31 has just been released

2020-03-22 Thread Benjamin Mahler
Thanks Marc, do you have any broader comments on the implications of
iouring for libev? It looks like iouring is finally bringing async system
calls (not just async io) to Linux. Will libeio have an iouring backend
that doesn't use a thread pool and instead hands the io off to the kernel
with io_uring?

In the Mesos project we have been using libev for some time, but in oder to
get the benefits of iouring we'd want to be handing off the work to the
kernel via iouring and not use io threads. Will libeio be providing this?

On Thu, Mar 19, 2020 at 4:34 AM Marc Lehmann  wrote:

> > Currently, the io_uring interface evelopment in libev is on hold,
> awaiting
>
> I might add, the iouring backend can be enabled in libev-4.33, and is
> expected to work. It has not really received testing, and it doesn't seem
> to
> have speed benefits yet.
>
> Anybody is invited to experiment with it - just don't use it in production.
>
> --
> The choice of a   Deliantra, the free code+content
> MORPG
>   -==- _GNU_  http://www.deliantra.net
>   ==-- _   generation
>   ---==---(_)__  __   __  Marc Lehmann
>   --==---/ / _ \/ // /\ \/ /  schm...@schmorp.de
>   -=/_/_//_/\_,_/ /_/\_\
>
>
___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev