svn commit: r366697 - head/usr.bin/xinstall
Mateusz Guzik
mjguzik at gmail.com
Wed Oct 14 13:29:03 UTC 2020
This should use copy_file_range (also available on Linux).
On 10/14/20, Alex Richardson <arichardson at freebsd.org> wrote:
> Author: arichardson
> Date: Wed Oct 14 12:28:41 2020
> New Revision: 366697
> URL: https://svnweb.freebsd.org/changeset/base/366697
>
> Log:
> install(1): Avoid unncessary fstatfs() calls and use mmap() based on size
>
> According to git blame the trymmap() function was added in 1996 to skip
> mmap() calls for NFS file systems. However, nowadays mmap() should be
> perfectly safe even on NFS. Importantly, onl ufs and cd9660 file systems
> were whitelisted so we don't use mmap() on ZFS. It also prevents the use
> of mmap() when bootstrapping from macOS/Linux since on those systems the
> trymmap() function was always returning zero due to the missing
> MFSNAMELEN
> define.
>
> This change keeps the trymmap() function but changes it to check whether
> using mmap() can reduce the number of system calls that are required.
> Using mmap() only reduces the number of system calls if we need multiple
> read()
> syscalls, i.e. if the file size is > MAXBSIZE. However, mmap() is more
> expensive
> than read() so this sets the threshold at 4 fewer syscalls. Additionally,
> for
> larger file size mmap() can significantly increase the number of page
> faults,
> so avoid it in that case.
>
> It's unclear whether using mmap() is ever faster than a read with an
> appropriate
> buffer size, but this change at least removes two unnecessary system
> calls
> for every file that is installed.
>
> Reviewed By: markj
> Differential Revision: https://reviews.freebsd.org/D26041
>
> Modified:
> head/usr.bin/xinstall/xinstall.c
>
> Modified: head/usr.bin/xinstall/xinstall.c
> ==============================================================================
> --- head/usr.bin/xinstall/xinstall.c Wed Oct 14 10:12:39 2020 (r366696)
> +++ head/usr.bin/xinstall/xinstall.c Wed Oct 14 12:28:41 2020 (r366697)
> @@ -148,7 +148,7 @@ static void metadata_log(const char *, const char *, s
> const char *, const char *, off_t);
> static int parseid(const char *, id_t *);
> static int strip(const char *, int, const char *, char **);
> -static int trymmap(int);
> +static int trymmap(size_t);
> static void usage(void);
>
> int
> @@ -1087,7 +1087,7 @@ compare(int from_fd, const char *from_name __unused,
> s
> if (do_digest)
> digest_init(&ctx);
> done_compare = 0;
> - if (trymmap(from_fd) && trymmap(to_fd)) {
> + if (trymmap(from_len) && trymmap(to_len)) {
> p = mmap(NULL, from_len, PROT_READ, MAP_SHARED,
> from_fd, (off_t)0);
> if (p == MAP_FAILED)
> @@ -1248,13 +1248,8 @@ copy(int from_fd, const char *from_name, int to_fd,
> co
>
> digest_init(&ctx);
>
> - /*
> - * Mmap and write if less than 8M (the limit is so we don't totally
> - * trash memory on big files. This is really a minor hack, but it
> - * wins some CPU back.
> - */
> done_copy = 0;
> - if (size <= 8 * 1048576 && trymmap(from_fd) &&
> + if (trymmap((size_t)size) &&
> (p = mmap(NULL, (size_t)size, PROT_READ, MAP_SHARED,
> from_fd, (off_t)0)) != MAP_FAILED) {
> nw = write(to_fd, p, size);
> @@ -1523,20 +1518,23 @@ usage(void)
> * return true (1) if mmap should be tried, false (0) if not.
> */
> static int
> -trymmap(int fd)
> +trymmap(size_t filesize)
> {
> -/*
> - * The ifdef is for bootstrapping - f_fstypename doesn't exist in
> - * pre-Lite2-merge systems.
> - */
> -#ifdef MFSNAMELEN
> - struct statfs stfs;
> -
> - if (fstatfs(fd, &stfs) != 0)
> - return (0);
> - if (strcmp(stfs.f_fstypename, "ufs") == 0 ||
> - strcmp(stfs.f_fstypename, "cd9660") == 0)
> - return (1);
> -#endif
> - return (0);
> + /*
> + * This function existed to skip mmap() for NFS file systems whereas
> + * nowadays mmap() should be perfectly safe. Nevertheless, using mmap()
> + * only reduces the number of system calls if we need multiple read()
> + * syscalls, i.e. if the file size is > MAXBSIZE. However, mmap() is
> + * more expensive than read() so set the threshold at 4 fewer syscalls.
> + * Additionally, for larger file size mmap() can significantly increase
> + * the number of page faults, so avoid it in that case.
> + *
> + * Note: the 8MB limit is not based on any meaningful benchmarking
> + * results, it is simply reusing the same value that was used before
> + * and also matches bin/cp.
> + *
> + * XXX: Maybe we shouldn't bother with mmap() at all, since we use
> + * MAXBSIZE the syscall overhead of read() shouldn't be too high?
> + */
> + return (filesize > 4 * MAXBSIZE && filesize < 8 * 1024 * 1024);
> }
> _______________________________________________
> svn-src-all at freebsd.org mailing list
> https://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
>
--
Mateusz Guzik <mjguzik gmail.com>
More information about the svn-src-head
mailing list