about summary refs log tree commit homepage
path: root/lib/PublicInbox/DS.pm
DateCommit message (Collapse)
2019-06-24ds: favor `delete' over assigning fields to `undef'
This is cleaner in most cases and may allow Perl to reuse memory from unused fields. We can do this now that we no longer support Perl 5.8; since Danga::Socket was written with struct-like pseudo-hash support in mind, and Perl 5.9+ dropped support for pseudo-hashes over a decade ago.
2019-06-24ds: get rid of event_watch field
We don't need to keep track of that field since we always know what events we're interested in when using one-shot wakeups.
2019-06-24ds: remove IO::Poll support (for now)
It may be reinstated at a later time if there's interest; but I want to be able to use one-shot notifications for certain events while retaining level-triggered notifications others. OTOH, I intend to fully support kqueue; via IO::KQueue for now, but via syscall() eventually to take advantage of the syscall reduction kevent(2) can provide over (current) epoll APIs.
2019-06-24ds: share watch_chg between watch_read/watch_write
There was much duplicate logic between watch_read and watch_write. Share that logic, and give us room to enable edge-triggered or one-shot notifications in the future.
2019-06-24ds: import IO::KQueue namespace
Make the rest of our IO::KQueue-using code less verbose and closer to the C equivalent.
2019-06-24ds: set event flags directly at initialization
We can avoid the EPOLL_CTL_ADD && EPOLL_CTL_MOD sequence with a single EPOLL_CTL_ADD.
2019-06-24ds: get rid of redundant and unnecessary POLL* constants
EPOLL* constants already match their POLL* counterparts and there's no way Linux can ever diverge or change the values of those constants. So we'll favor the EPOLL* ones since we use EPOLLEXCLUSIVE, already. For weird stuff like kqueue, we'd need to keep maintaining the mapping, anyways.
2019-06-24ds: switch write buffering to use a tempfile
Data which can't fit into a generously-sized socket buffer, has no business being stored in heap.
2019-06-24ds: share send(..., MSG_MORE) logic
No sense in having similar Linux-specific functionality in both our NNTP.pm and HTTP.pm
2019-06-24ds: remove support for DS->write(undef)
We call ->flush_write directly, now; so we can eliminate a needless check.
2019-06-24ds: don't pass `events' arg to EPOLL_CTL_DEL
There's no point in passing a mask of interesting events when removing an item from the epoll watch set.
2019-06-24ds: lazy-initialize wbuf
We don't need write buffering unless we encounter slow clients requesting large responses. So don't waste a hash slot or (empty) arrayref for it.
2019-06-24ds: split out from ->flush_write and ->write
Get rid of the confusing $need_queue variable and all the associated documentation for it. Instead, make it obvious that we're either skipping the write buffer or flushing the write buffer by splitting the sub in two.
2019-06-24ds: lazy initialize wbuf_off
Since Perl 5.10+, "fields" makes a restricted hash; not a compile-time-defined array (struct) with fixed offsets as it did in Perl <= 5.8. Thus in-use fields cost memory, and since the write buffer offset is rarely needed; stop relying on it.
2019-06-24ds: get rid of on_incomplete_write wrapper
Wrong place to be wrapping this method.
2019-06-24AddTimer: avoid clock_gettime for the '0' case
We rely on immediate timers often, so we can avoid the overhead of an extra subroutine call to retrieve the monotonic time (and a sometimes-system call on some platforms).
2019-06-24ds: use and export monotonic now()
All of our internal timing code should use monotonic clocks for consistency against system clock adjustments. This can be shared by our Daemon and NNTP packages.
2019-06-24ds: get rid of more unused debug instance methods
Over a decade of using Danga::Socket and I never found the built-in debug functionality useful.
2019-06-24ds: get rid of {closed} field
Merely checking the presence of the {sock} field is enough, and having multiple sources of truth increases confusion and the likelyhood of bugs.
2019-06-16ds: stop distinguishing event read and write callbacks
Having separate read/write callbacks in every class is too confusing to my easily-confused mind. Instead, give every class an "event_step" callback which is easier to wrap my head around. This will make future code to support IO::Socket::SSL-wrapped sockets easier-to-digest, since SSL_write() can require waiting on POLLIN events, and SSL_read() can require waiting on POLLOUT events.
2019-06-10ds: stop caring about event flags set by epoll/poll/kqueue
If we got something to write, then write it. Otherwise, try reading; and continue dealing with errors which normally occur along the way. Trying to read requests while we need to buffer in luserspace is suicidal from a memory management standpoint. The only adjustment needed for existing callers is EvCleanup; where we need to ensure we're always calling the dummy EvCleanup::event_write callback to accomplish nothing.
2019-06-10ds: do not distinguish between POLLHUP and POLLERR
In my experience, both are worthless as any normal read/write call path will be wanting to check errors and deal with them appropriately; so we can just call event_read, for now. Eventually, there'll probably be only one callback for dealing with all in/out/err/hup events to simplify logic, especially w.r.t TLS socket negotiation.
2019-06-10ds: remove read method, here, too
Since we stop using it in NNTP, we don't need it at all.
2019-06-10ds: remove steal_socket method
We won't be needing it, not even for TLS support.
2019-06-10ds: remove {fd} field
Storing the file descriptor was redundant as we can quickly call fileno($self->{sock}) and not have to store an extra hash table entry. Multiple sources of truth leads to confusion, confusion leads to bugs.
2019-06-10ds: reduce Errno imports and drop ->close reason
ECONNRESET and EPIPE are common on a big Internet filled with unreliable connections, and there's nothing our code can do about it. So no point in wasting code to log them and there are plenty of tracing tools to choose from if such diagnostics are needed.
2019-06-10ds: cleanup Errno imports and favor constant comparisons
Stop importing unused constants, and favor integer comparisons of `$!' over `$!{EFOO}' hash lookups. Integer comparisons are slightly faster, even: Benchmark: timing 30 iterations of cmp_eq, cmp_ne, hash_hit, hash_miss... cmp_eq: 1 wallclock secs ( 1.61 usr + 0.00 sys = 1.61 CPU) @ 18.63/s (n=30) cmp_ne: 2 wallclock secs ( 1.57 usr + 0.00 sys = 1.57 CPU) @ 19.11/s (n=30) hash_hit: 4 wallclock secs ( 3.85 usr + 0.00 sys = 3.85 CPU) @ 7.79/s (n=30) hash_miss: 4 wallclock secs ( 3.74 usr + 0.00 sys = 3.74 CPU) @ 8.02/s (n=30) #!/usr/bin/perl -w use Benchmark qw(:all); use Errno qw(EAGAIN EINTR); my ($r, $w); pipe($r, $w) or die 'pipe'; require IO::Handle; $r->blocking(0); my $buf; my $n = 30000; timethese(30, { hash_hit => sub { sysread($r, $buf, 1); for (0..$n) { next if $!{EAGAIN}; die 'FAIL'; } } , 'cmp_eq' => sub { sysread($r, $buf, 1); for (0..$n) { next if $! == EAGAIN; die 'FAIL'; } }, hash_miss => sub { sysread($r, $buf, 1); for (0..$n) { die 'FAIL' if $!{EINTR}; } }, 'cmp_ne' => sub { sysread($r, $buf, 1); for (0..$n) { die 'FAIL' if $! == EINTR; } }, });
2019-06-10ds: simplify write buffer accounting
Keeping track of write_buf_size was redundant and pointless when we can simply check the number of elements in the buffer array. Multiple sources of truth leads to confusion; confusion leads to bugs. Finally, rename the prefixes to 'wbuf' to ensure we loudly (instead of silently) break any external dependencies being ported over from Danga::Socket, as further changes are pending.
2019-06-03ds: remove PLCMap and per-socket PostLoopCallback
We don't need and won't be needing per-socket PostLoopCallbacks.
2019-06-02ds: drop write_set_watch field
We never enable write watches ourselves for HTTP and NNTP, and only enable the write watch with EvCleanup because it's an "always on" watch.
2019-06-02ds: drop unused EVENT: label in epoll code path
This was never used in Danga::Socket 1.61, either.
2019-06-02ds: drop checks for invalid descriptors
I've used Danga::Socket for well over a decade in various projects at this point and have never seen the need for it. If such a bug ever happens; the process should fall over so it gets fixed ASAP.
2019-06-02ds: drop set_writer_func support
This is not used by perlbal for OpenSSL support, either; and it does not appear to be the right layer for doing write translations anyways (IO::Socket::SSL uses `tie').
2019-06-02ds: add a note about planned future changes
Sometimes I get bored with the email part of this project and need a distraction :P
2019-06-02ds: drop more unused subs
ToClose and HaveEpoll are of no use to us and I see no future use for them, either.
2019-06-01ds: fix and test for FD leaks with kqueue on ->Reset
Even though we currently don't use it repeatedly, ->Reset should close() kqueue FDs and not cause the process to run out of descriptors. Add a close-on-exec test while we're at it.
2019-06-01ds: set close-on-exec flag on epoll descriptors
We should not be leaking these FDs to git(1) processes, in case git has a bug that causes it to access the wrong FD.
2019-05-22DS: warn on deprecations
Enabling deprecation warnings didn't seem to have any noticeable effects with "perl -w -c", so whatever reason Danga had for it is long irrelevant.
2019-05-22DS: remove IPPROTO_TCP import
Unlike Danga::Socket, we do not support TCP_CORK, either
2019-05-22DS: drop $VERSION var
It was only relevant to Danga::Socket.
2019-05-22DS: remove support OtherFds code
It's easy enough to wrap FDs in classes that can use all of the functionality of the event loop, not just the read-only interface AddOtherFds provided.
2019-05-22DS: get rid of unused methods and aliases
"make syntax" is clean, now
2019-05-08DS: epoll: fix misordered EPOLL_CTL_DEL call
Any operations on an fd after POSIX::close() are invalid, so epoll_ctl will fail. Worse off, in a multi-threaded Perl, the fd may be reused by another thread and EPOLL_CTL_DEL can hit the wrong file description as a result. cf. https://rt.cpan.org/Ticket/Display.html?id=129487
2019-05-08DS: drop unused "_undef" sub
No longer used since we removed the *_ip_string fields
2019-05-08DS: handle EINTR in IO::Poll path, too
IO::Poll::_poll returns -1, which is "true" to Perl. cf. https://rt.cpan.org/Ticket/Display.html?id=129484
2019-05-05DS: workaround IO::Kqueue EINTR (mis-)handling
IO::Kqueue seems unmaintained, so workaround a long-standing bug where it falls over on signals: https://rt.cpan.org/Ticket/Display.html?id=116615
2019-05-05DS: drop profiling support
There's other ways to profile and we don't need to add runtime branches to do this.
2019-05-05DS: remove unused fields and functions
More will likely be dropped in the future, but drop the obvious ones we aren't using, for now; especially since some of them are set at ->new time and unavoidable. This saves 579 bytes per-client on my 64-bit Debian stable system as measured by Devel::Size::total_size from PublicInbox::HTTP::event_read. This adds up in C10K or C100K situations. Things we drop are: * corked - MSG_MORE requires fewer syscalls * read_push_back - tried to use it, ate CPU with slow clients * IP/port fields - accept() already returns what we care about
2019-05-05listener: use EPOLLEXCLUSIVE for listen sockets
Since our listen sockets are non-blocking and we may run multiple httpd|nntpd processes; we need a way to avoid thundering herds when there are multiple httpd|nntpd worker processes. EPOLLEXCLUSIVE was added just for that in Linux 4.5
2019-05-04bundle Danga::Socket and Sys::Syscall
These modules are unmaintained upstream at the moment, but I'll be able to help with the intended maintainer once/if CPAN ownership is transferred. OTOH, we've been waiting for that transfer for several years, now... Changes I intend to make: * EPOLLEXCLUSIVE for Linux * remove unused fields wasting memory * kqueue bugfixes e.g. https://rt.cpan.org/Ticket/Display.html?id=116615 * accept4 support And some lower priority experiments: * switch to EV_ONESHOT / EPOLLONESHOT (incompatible changes) * nginx-style buffering to tmpfile instead of string array * sendfile off tmpfile buffers * io_uring maybe?