NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: bin/60443: ftp ASCII transfers are too slow
The following reply was made to PR bin/60443; it has been noted by GNATS.
From: Luke Mewburn <luke%mewburn.net@localhost>
To: gnats-bugs%netbsd.org@localhost
Cc: gnats-admin%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost
Subject: Re: bin/60443: ftp ASCII transfers are too slow
Date: Sun, 19 Jul 2026 18:02:56 +1000
On 26-07-12 08:00, rvp%SDF.ORG@localhost via gnats wrote:
| FTP ASCII transfers seem to interact badly with Nagle's algorithm
| because ASCII xfers rely on libc's BUFSIZ (1KB) internal buffer.
|
| If you write 1KB at a time (relatively slowly because you're doing
| getc(3)/putc(3) to locale '\n'), then it looks the 200ms Nagle timeout
| comes into play.
|
| At that's what it seems to me from looking at the tcpdump packet times.
|
| ---START patch ftp(1)---
| diff -urN usr.bin/ftp.orig/ftp.c usr.bin/ftp/ftp.c
| --- usr.bin/ftp.orig/ftp.c 2026-02-07 03:55:18.973125260 +0000
| +++ usr.bin/ftp/ftp.c 2026-02-08 15:51:14.124404272 +0000
| @@ -1728,6 +1728,23 @@
| return (1);
| }
|
| +static FILE *
| +ftp_fdopen(int fd, const char *lmode)
| +{
| + enum { BSIZ = XFERBUFMIN * 4 }; /* 4K (any >MTU) */
I think we could use a similar buffer sizing logic to what I
implemented in ftp.c 1.181 on 2026/02/07 in recvrequest():
if (rcvbuf_size == 0)
bufsize = XFERBUFMAX;
else
bufsize = MAX(XFERBUFMIN, MIN(rcvbuf_size, XFERBUFMAX));
(maybe this logic could be centralized for easier reuse).
Unless this will cause issues on low memory systems with large
stdio buffer and separate binary mode read buffer?
| + FILE *fp;
| + void* buf;
| +
| + if ((fp = fdopen(fd, lmode)) == NULL)
| + return NULL;
| + if ((buf = ftp_malloc(BSIZ)) == NULL) {
| + fclose(fp);
| + return NULL;
| + }
| + (void)setvbuf(fp, buf, _IOFBF, BSIZ);
Doesn't this leak "buf" because we've allocated it?
What if we just call setvbuf() with buf==NULL which
should let the stdio cleanup when the FILE is closed?
I've done a bit of reading into different setvbuf()
man pages (POSIX, Linux, NetBSD, macOS, cppreference), and it
seems that all support auto-allocating if buf==NULL and freeing
on close.
POSIX setvbuf(3) states (https://pubs.opengroup.org/onlinepubs/9699919799/functions/setvbuf.html):
If buf is not a null pointer, the array it points to may be used
instead of a buffer allocated by setvbuf() and the argument size
specifies the size of the array; otherwise, size may determine
the size of a buffer allocated by the setvbuf() function.
Linux setvbuf(3) states:
If the argument buf is NULL, only the mode is affected;
a new buffer will be allocated on the next read or write
operation.
However, NetBSD setvbuf(3) states:
(If the size argument is not zero but buf is NULL,
a buffer of the given size will be allocated immediately,
and released on close. This is an extension to ANSI C;
portable code should use a size of 0 with any NULL buffer.)
macOS has a variation of this - understandable since both are 4.xBSD
derived man pages.
cppreference.com (https://en.cppreference.com/c/io/setvbuf)
If buffer is a null pointer, resizes the internal buffer to
size.
regards,
Luke.
Home |
Main Index |
Thread Index |
Old Index