[Libguestfs] [PATCH libnbd v3 3/3] copy: Evict pages from the page cache when writing to local files.

Eric Blake eblake at redhat.com
Thu Feb 25 21:48:19 UTC 2021


On 2/25/21 11:34 AM, Richard W.M. Jones wrote:
> When writing to a file or block device, we are always writing new
> (ie. previously uncached) data.  This commit ensures that very little
> of that data will be in the page cache after nbdcopy finishes by
> evicting it as we go along.  This ensures that the host page cache is
> largely unchanged for other host processes.
> 
> This uses Linus's technique described here:
> https://stackoverflow.com/a/3756466
> but instead of using 2 windows, it uses a configurable larger number
> of windows (in this case 8).

Here you state configurable...

> 
> Before this commit:
> 
>   $ rm /var/tmp/pattern ; sync ; time ./run nbdcopy [ nbdkit pattern 32G ] /var/tmp/pattern && cachestats /var/tmp/pattern
>   real	0m34.852s
>   user	0m18.368s
>   sys	0m33.117s
>   pages in cache: 7090389/8388608 (84.5%)  [filesize=33554432.0K, pagesize=4K]
> 
> Notice that the newly written file ends up in the cache, thus trashing
> the page cache on the host.
> 
> After this commit:
> 
>   $ rm /var/tmp/pattern ; sync ; time ./run nbdcopy [ nbdkit pattern 32G ] /var/tmp/pattern && cachestats /var/tmp/pattern
>   real	0m38.721s
>   user	0m18.837s
>   sys	0m40.654s
>   pages in cache: 65536/8388608 (0.8%)  [filesize=33554432.0K, pagesize=4K]
> 
> The newly written file does not disturb the page cache.  However there
> is about 11% slow down.

I suspect that is because we end up waiting longer for flushing actions
to complete before evicting things from cache.  Do we want this to be an
opt-in/out knob on the command line?  If so, which way should we lean
for the default value of that knob?

> @@ -159,7 +165,60 @@ page_cache_evict (struct rw_file *rwf, uint64_t orig_offset, size_t orig_len)
>      len -= n;
>    }
>  }
> -#endif
> +#endif /* PAGE_CACHE_MAPPING */
> +
> +#ifdef EVICT_WRITES
> +/* Prepare to evict file contents from the page cache when writing.
> + * We cannot do this directly (as for reads above) because we have to
> + * wait for Linux to finish writing the pages to disk.  Therefore the
> + * strategy is to (1) tell Linux to begin writing asynchronously and
> + * (2) evict the previous pages, which have hopefully been written
> + * already by the time we get here.  We have to maintain window(s) per
> + * thread.
> + *
> + * For more information see https://stackoverflow.com/a/3756466 and
> + * the links to Linus's advice from that entry.
> + */

I'm less familiar with this interface (having never used it before), but
your usage patterns appear to match the man page and reference materials.

> +
> +/* Increasing the number of windows gives better performance since
> + * writes are given more time to make it to disk before we have to
> + * pause to do the page cache eviction.  But a larger number of
> + * windows means less success overall since (a) more page cache is
> + * used as the program runs, and (b) we don't evict any writes which
> + * are still pending when the program exits.
> + */
> +#define NR_WINDOWS 8

...but here you have a #define.  Are you missing a command line option,
or saving it for a later patch on top?

Otherwise it looks reasonable, once you decide what command-line tuning
it might need (as the choice between speed vs. cache clobbering may be
something users want to make).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org




More information about the Libguestfs mailing list