On Fri, Sep 02, 2016 at 10:33:19AM +0200, Andreas Bartelt wrote:
> On 09/02/16 10:24, Alexander Bluhm wrote:
> > I see a performance drop to 10 Mbit/sec on some old i386 machines
> > with em(4).  Can you try this kernel diff to see wether it is the
> > same problem?
> > 
> 
> yes, >50 MB/s now. Thanks!

So I think this happens:

sosend() uses m_getuio() now to allocate a MAXMCLBYTES mbuf cluster,
that is 65536 bytes.  sbreserve() calculates the upper cluster limit
min(cc * 2, sb_max + (sb_max / MCLBYTES) * MSIZE).  In our case it
is min(1024*16 * 2, (256*1024) + ((256*1024) / (1 << 11)) * 256)
== min(32768, 294912) == 32768.

So after allocating a single mbuf cluster the sending socket buffer
has no space anymore.  As tcp_output() keeps the mbuf cluster for
retransmits, it will be freed only after all ACKs have been received.
That kills performance totally.

To allow cycling through the mbufs periodically, I think we need
space for at least 3 of them.  Note that this diff also affects the
mbuf size on the receiving side, but I think it does not matter
much as the data size is also limited.

Andreas, can you revert the diff I sent previously and try this one
instead?

ok?

bluhm

Index: kern/uipc_socket2.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_socket2.c,v
retrieving revision 1.64
diff -u -p -r1.64 uipc_socket2.c
--- kern/uipc_socket2.c 28 Jun 2016 14:47:00 -0000      1.64
+++ kern/uipc_socket2.c 2 Sep 2016 10:29:10 -0000
@@ -397,7 +397,8 @@ sbreserve(struct sockbuf *sb, u_long cc)
        if (cc == 0 || cc > sb_max)
                return (1);
        sb->sb_hiwat = cc;
-       sb->sb_mbmax = min(cc * 2, sb_max + (sb_max / MCLBYTES) * MSIZE);
+       sb->sb_mbmax = max(3 * MAXMCLBYTES,
+           min(cc * 2, sb_max + (sb_max / MCLBYTES) * MSIZE));
        if (sb->sb_lowat > sb->sb_hiwat)
                sb->sb_lowat = sb->sb_hiwat;
        return (0);

Reply via email to