Re: [PATCH 2/4] populate: remove file creation loops that take forever

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]



On Tue, Jan 17, 2023 at 04:44:02PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@xxxxxxxxxx>
> 
> Replace the file creation loops with a perl script that does everything
> we want from a single process.  This reduces the runtime of
> _scratch_xfs_populate substantially by avoiding thousands of execve
> overhead.  On my system, this reduces the runtime of xfs/349 (with scrub
> enabled) from ~140s to ~45s.
> 
> Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
> ---

Looks good to me,

Reviewed-by: Zorro Lang <zlang@xxxxxxxxxx>

>  common/populate |   61 ++++++++++++++++++-----------------------------
>  src/popdir.pl   |   72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 96 insertions(+), 37 deletions(-)
>  create mode 100755 src/popdir.pl
> 
> 
> diff --git a/common/populate b/common/populate
> index 84f4b8e374..180540aedd 100644
> --- a/common/populate
> +++ b/common/populate
> @@ -11,6 +11,7 @@ _require_populate_commands() {
>  	_require_xfs_io_command "falloc"
>  	_require_xfs_io_command "fpunch"
>  	_require_test_program "punch-alternating"
> +	_require_test_program "popdir.pl"
>  	case "${FSTYP}" in
>  	"xfs")
>  		_require_command "$XFS_DB_PROG" "xfs_db"
> @@ -54,55 +55,50 @@ __populate_fragment_file() {
>  
>  # Create a large directory
>  __populate_create_dir() {
> -	name="$1"
> -	nr="$2"
> -	missing="$3"
> +	local name="$1"
> +	local nr="$2"
> +	local missing="$3"
> +	shift; shift; shift
>  
>  	mkdir -p "${name}"
> -	seq 0 "${nr}" | while read d; do
> -		creat=mkdir
> -		test "$((d % 20))" -eq 0 && creat=touch
> -		$creat "${name}/$(printf "%.08d" "$d")"
> -	done
> +	$here/src/popdir.pl --dir "${name}" --end "${nr}" "$@"
>  
>  	test -z "${missing}" && return
> -	seq 1 2 "${nr}" | while read d; do
> -		rm -rf "${name}/$(printf "%.08d" "$d")"
> -	done
> +	$here/src/popdir.pl --dir "${name}" --start 1 --incr 2 --end "${nr}" --remove "$@"
>  }
>  
>  # Create a large directory and ensure that it's a btree format
>  __populate_xfs_create_btree_dir() {
>  	local name="$1"
>  	local isize="$2"
> -	local missing="$3"
> +	local dblksz="$3"
> +	local missing="$4"
>  	local icore_size="$(_xfs_get_inode_core_bytes $SCRATCH_MNT)"
>  	# We need enough extents to guarantee that the data fork is in
>  	# btree format.  Cycling the mount to use xfs_db is too slow, so
>  	# watch for when the extent count exceeds the space after the
>  	# inode core.
>  	local max_nextents="$(((isize - icore_size) / 16))"
> -	local nr=0
> +	local nr
> +	local incr
> +
> +	# Add about one block's worth of dirents before we check the data fork
> +	# format.
> +	incr=$(( (dblksz / 8) / 100 * 100 ))
>  
>  	mkdir -p "${name}"
> -	while true; do
> -		local creat=mkdir
> -		test "$((nr % 20))" -eq 0 && creat=touch
> -		$creat "${name}/$(printf "%.08d" "$nr")"
> +	for ((nr = 0; ; nr += incr)); do
> +		$here/src/popdir.pl --dir "${name}" --start "${nr}" --end "$((nr + incr - 1))"
> +
>  		# Extent count checks use data blocks only to avoid the removal
>  		# step from removing dabtree index blocks and reducing the
>  		# number of extents below the required threshold.
> -		if [ "$((nr % 40))" -eq 0 ]; then
> -			local nextents="$(xfs_bmap ${name} | grep -v hole | wc -l)"
> -			[ "$((nextents - 1))" -gt $max_nextents ] && break
> -		fi
> -		nr=$((nr+1))
> +		local nextents="$(xfs_bmap ${name} | grep -v hole | wc -l)"
> +		[ "$((nextents - 1))" -gt $max_nextents ] && break
>  	done
>  
>  	test -z "${missing}" && return
> -	seq 1 2 "${nr}" | while read d; do
> -		rm -rf "${name}/$(printf "%.08d" "$d")"
> -	done
> +	$here/src/popdir.pl --dir "${name}" --start 1 --incr 2 --end "${nr}" --remove
>  }
>  
>  # Add a bunch of attrs to a file
> @@ -224,9 +220,7 @@ _scratch_xfs_populate() {
>  
>  	# Fill up the root inode chunk
>  	echo "+ fill root ino chunk"
> -	seq 1 64 | while read f; do
> -		$XFS_IO_PROG -f -c "truncate 0" "${SCRATCH_MNT}/dummy${f}"
> -	done
> +	$here/src/popdir.pl --dir "${SCRATCH_MNT}" --start 1 --end 64 --format "dummy%u" --file-mult 1
>  
>  	# Regular files
>  	# - FMT_EXTENTS
> @@ -261,7 +255,7 @@ _scratch_xfs_populate() {
>  
>  	# - BTREE
>  	echo "+ btree dir"
> -	__populate_xfs_create_btree_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BTREE" "$isize" true
> +	__populate_xfs_create_btree_dir "${SCRATCH_MNT}/S_IFDIR.FMT_BTREE" "$isize" "$dblksz" true
>  
>  	# Symlinks
>  	# - FMT_LOCAL
> @@ -340,14 +334,7 @@ _scratch_xfs_populate() {
>  	local rec_per_btblock=16
>  	local nr="$(( 2 * (blksz / rec_per_btblock) * ino_per_rec ))"
>  	local dir="${SCRATCH_MNT}/INOBT"
> -	mkdir -p "${dir}"
> -	seq 0 "${nr}" | while read f; do
> -		touch "${dir}/${f}"
> -	done
> -
> -	seq 0 2 "${nr}" | while read f; do
> -		rm -f "${dir}/${f}"
> -	done
> +	__populate_create_dir "${dir}" "${nr}" true --file-mult 1
>  
>  	# Reverse-mapping btree
>  	is_rmapbt="$(_xfs_has_feature "$SCRATCH_MNT" rmapbt -v)"
> diff --git a/src/popdir.pl b/src/popdir.pl
> new file mode 100755
> index 0000000000..dc0c046b7d
> --- /dev/null
> +++ b/src/popdir.pl
> @@ -0,0 +1,72 @@
> +#!/usr/bin/perl -w
> +
> +# Copyright (c) 2023 Oracle.  All rights reserved.
> +# SPDX-License-Identifier: GPL-2.0
> +#
> +# Create a bunch of files and subdirs in a directory.
> +
> +use Getopt::Long;
> +use File::Basename;
> +
> +$progname=$0;
> +GetOptions("start=i" => \$start,
> +	   "end=i" => \$end,
> +	   "file-mult=i" => \$file_mult,
> +	   "incr=i" => \$incr,
> +	   "format=s" => \$format,
> +	   "dir=s" => \$dir,
> +	   "remove!" => \$remove,
> +	   "help!" => \$help,
> +	   "verbose!" => \$verbose);
> +
> +
> +# check/remove output directory, get filesystem info
> +if (defined $help) {
> +  # newline at end of die message suppresses line number
> +  print STDERR <<"EOF";
> +Usage: $progname [options]
> +Options:
> +  --dir             chdir here before starting
> +  --start=num       create names starting with this number (0)
> +  --incr=num        increment file number by this much (1)
> +  --end=num         stop at this file number (100)
> +  --file-mult       create a regular file when file number is a multiple
> +                    of this quantity (20)
> +  --remove          remove instead of creating
> +  --format=str      printf formatting string for file name ("%08d")
> +  --verbose         verbose output
> +  --help            this help screen
> +EOF
> +  exit(1) unless defined $help;
> +  # otherwise...
> +  exit(0);
> +}
> +
> +if (defined $dir) {
> +	chdir($dir) or die("chdir $dir");
> +}
> +$start = 0 if (!defined $start);
> +$end = 100 if (!defined $end);
> +$file_mult = 20 if (!defined $file_mult);
> +$format = "%08d" if (!defined $format);
> +$incr = 1 if (!defined $incr);
> +
> +for ($i = $start; $i <= $end; $i += $incr) {
> +	$fname = sprintf($format, $i);
> +
> +	if ($remove) {
> +		$verbose && print "rm $fname\n";
> +		unlink($fname) or rmdir($fname) or die("unlink $fname");
> +	} elsif ($file_mult == 0 or ($i % $file_mult) == 0) {
> +		# create a file
> +		$verbose && print "touch $fname\n";
> +		open(DONTCARE, ">$fname") or die("touch $fname");
> +		close(DONTCARE);
> +	} else {
> +		# create a subdir
> +		$verbose && print "mkdir $fname\n";
> +		mkdir($fname, 0755) or die("mkdir $fname");
> +	}
> +}
> +
> +exit(0);
> 




[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux