rpms/kcbench/F-7 kcbench, NONE, 1.1 kcbench-README, NONE, 1.1 kcbench.spec, NONE, 1.1

Thorsten Leemhuis (thl) fedora-extras-commits at redhat.com
Mon Oct 15 16:11:46 UTC 2007


Author: thl

Update of /cvs/pkgs/rpms/kcbench/F-7
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv13585

Added Files:
	kcbench kcbench-README kcbench.spec 
Log Message:
import package -- review #326831


--- NEW FILE kcbench ---
#!/bin/bash
#
# kcbench - kernel compile benchmark
# Copyright (c) 2007 Thorsten Leemhuis <fedora at leemhuis.info>
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#

# this is me
myprog_name=kcbench
myprog_version=0.1.1

# set some defaults -- called before cmdoptions are parsed
kcbench_init ()
{
	# verbose?
	verboselevel=2

	# results are normally stable, thus 3 runs after filling the cache should normally be enough
	default_number_of_iterations=3

	# used together with make -j 
	# number of CPUs * 2
	default_number_of_jobs=$(($(grep '^processor' < /proc/cpuinfo  | wc -l)*2))

	# we search for kernels to compile here
	# note that I didn't use /usr/src/ on purpose as localtion -- kernels there 
	# might be modified
	default_sources_dir="/usr/share/kcbench-data/"

	# optional: retrieve settings from file
	if [[ -e "${HOME}/.kcbench" ]]; then
		source "${HOME}/.kcbench"
	fi
}


# check everthing before starting
kcbench_startupchecks()
{
	# check for tools we need
	# thinkaboutme: there are likely more needed
	for tool in make gcc ld ; do
		if ! which ${tool} &> /dev/null ; then
			echo "Could not find ${tool}"
			exit 2
		fi
	done

	# check if cron or other stuff runs and give a warning
	if [[ ! "${ignore_running_apps}" ]]; then
		local runningtasks="$(echo $(ps -A | grep --word -e crond -e httpd -e atd -e sendmail -e smbd | awk '{print $4}' | sort | uniq))"
		if [[ "${runningtasks}" ]] ; then
			echo "WARNING: The following daemons run and might disturb the benchmark: ${runningtasks}; use '--ignore-running-apps' to disabled this warning" >&2
			sleep 5
		fi
	fi


	# find a srctree to compile!
	if [[ "${compile_srctree}" ]]; then
		# user provided some informations what kernel to use
		if [[ -e "${compile_srctree}/include/linux/kernel.h" ]] ; then
			# is a local tree -- but we need the full path!
			if [[ "${compile_srctree}" == "${compile_srctree##/}" ]]; then
				dir_sources="${PWD}/${compile_srctree}"
			else
				dir_sources="${compile_srctree}"
			fi
		elif [[ -e "${default_sources_dir}/linux-${compile_srctree}/include/linux/kernel.h" ]]; then
			# user meant one of our trees by just giving version number
			dir_sources="${default_sources_dir%%/}/linux-${compile_srctree%%/}/"
		else
			echo "Could neither find directory ${compile_srctree} nor ${default_sources_dir%%/}/linux-${compile_srctree%%/}/" >&2
			exit 2
		fi
	else
		# we are own our own

		# without our std-dir it doesn't make sense to continue
		if [[ ! -d "${default_sources_dir}" ]]; then
			echo "${default_sources_dir} not found." >&2
			exit 2
		fi

		# use the latest one by default
		dir_sources="${default_sources_dir%%/}/$(ls -r "${default_sources_dir}" | head -n 1)"
		if [[ ! -e "${dir_sources}/include/linux/kernel.h" ]]; then
			echo "Found ${default_sources_dir}, but doesn't look like a kernel srctree." >&2
			exit 2
		fi
	fi


	# on testsystems the date often is set incorectly, thus check it to prevent misscompiles
	if (( $(date -r "${dir_sources}/Makefile" "+%s") > $(date "+%s") )); then
		echo "Makefile is younger then current date; please set your system time properly." >&2
		exit 2
	fi


	# create tempdir and remove it on exit
	trap 'kcbench_exit 127' 1 2 15
	if [[ "${dir_topoutput}" ]]; then
		# dir_topoutput present?
		if [[ ! -d "${dir_topoutput}" ]]; then
			echo "Could not find ${dir_topoutput}" >&2
			exit 2
		fi
		if [[ "${dir_topoutput}" == "${dir_topoutput##/}" ]]; then
			# we need the full path
			dir_topoutput="${PWD}/${dir_topoutput}"
		fi

		# if our dir in dir_topoutput exist already just use it
		if [[ -d "${dir_topoutput%%/}/${myprog_name}" ]]; then
			readonly dir_outputtmp="${dir_topoutput%%/}/${myprog_name}"
		else
			readonly dir_outputtmp=$(mktemp -d ${dir_topoutput%%/}/${myprog_name})
		fi
	else
		# use a tmp dir
		readonly dir_outputtmp=$(mktemp -d -t ${myprog_name}.XXXXXXXXX)
	fi

	# did dir get created?
	local returncode=$?
	if (( "${returncode}" > 0 )) || [[ ! -d "${dir_outputtmp}" ]]; then
		echo "Could not create temporary output directory" >&2 
		exit 2
	fi

	if [[ "${savefailedlogs}" ]] && [[ ! -d "${savefailedlogs}" ]] ; then
		echo "Could not find ${savefailedlogs}." >&2 
		exit 2
	fi


	# how many jobs?
	if [[ ! "${number_of_jobs}" ]]; then
		# use default
		number_of_jobs=${default_number_of_jobs}
	else
		# user provided number of jobs; but check user input
		for number in ${number_of_jobs}; do
			# is number_of_jobs a real number?
			if (( ! ${number} > 0 )) ; then
				echo "Please provide a real number together with --jobs" >&2
				exit 2
			fi
		done
	fi


	# is number_of_iterations a real number?
	if [[ ! "${number_of_iterations}" ]] ; then
		# use default
		if [[ "${run_infinite}" ]]; then 
			# when running infinite just 1
			number_of_iterations=1
		else
			number_of_iterations=${default_number_of_iterations}
		fi
	elif (( ! ${number_of_iterations} > 0 )) ; then
		echo "Please provide a real number together with --ilterations" >&2
		exit 2
	fi


	# create a logdirectory in dir_outputtmp
	[[ ! -d "${dir_outputtmp}/kcbench" ]] && mkdir "${dir_outputtmp}/kcbench"
	kcbench_logdir="${dir_outputtmp}/kcbench/"
	kcbench_logfile="${dir_outputtmp}/kcbench/log"
	touch "${kcbench_logfile}"



	# disable sceensaver (should we reset this? how?)
	setterm -blank 0
}


kcbench_exit()
{
	kcbench_echo 1 4 "Removing ${dir_outputtmp}"

	if [[ "${dir_outputtmp}" ]] && [[ -d "${dir_outputtmp}" ]]; then
		# the directory should contain our name, thus check it to be on the safe side
		if echo "${dir_outputtmp}" | grep "${myprog_name}" &> /dev/null ; then
			rm -rf "${dir_outputtmp}"
		else
			echo "Leaving ${dir_outputtmp} behind" >&2
		fi
	fi

	exit ${1}
}

kcbench_echo ()
{
	# where to output
	local this_fd=${1}
	shift

	# verboselevel
	local this_verbose=${1}
	shift

	# output
	if (( ${verboselevel} >= ${this_verbose} )); then
		echo "$@" >&${this_fd}
		echo "$@" >> "${kcbench_logfile}"
	fi
}

kcbench_main()
{
	# info
	kcebench_sysinfo 2

	# create defconfig
	kcbench_echo 1 3 "Creating default configuration with 'make defconfig'."
	make O="${dir_outputtmp}" -C "${dir_sources}" -j ${default_number_of_jobs} defconfig >> "${kcbench_logdir}"/make_defconfig 2>&1

	# prepration run
	if [[ ! "${no_cachefill}" ]]; then
		# Note: I tried to use something like this first:
		# find "${dir_sources}" -type f | grep -e '.h$'  -e '.c$' -e 'Makefile' -e 'Kconfig' -e 'Kbuild' -e '.S$' | xargs cat > /dev/null
		# But it does not work as good as a thrown-away compile-run

		# only print result in verbose mode
		(( ${verboselevel} == 2 )) && kcbench_echo 1 2 -n "Filling caches:     This might take a while..."
		kcbench_compile_kernel 3 ${default_number_of_jobs} run-0-fillcaches "Filling caches:     "
		kcbench_echo 1 3 "-------------------------------------------------------------------------------"
		# is there a better way to move the cursor to the left?
		(( ${verboselevel} == 2 )) && kcbench_echo 1 2 -e "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\bFilling caches:     Done                                                      "
	fi

	# go
	local totalruns=1
	local errorruns=0
	while : ; do
		for number in ${number_of_jobs}; do
			for ((run=1; run <= number_of_iterations ; run++)) ; do
				kcbench_compile_kernel 1 ${number} "run${totalruns}" "$(printf "%-20s" "Run ${totalruns} (-j ${number}):")"
				local returncode=$?
				if (( ${returncode} > 0 )); then
					let errorruns++
				fi
				let totalruns++
			done
		done

		if (( ${errorruns} > 0 )) ; then
			kcbench_echo 1 1 "Total erroruns:     ${errorruns}"
		fi

		if [[ ! "${run_infinite}" ]]; then
			# get out of the while loop
			break
		fi
	done
}


kcbench_compile_kernel()
{
	local this_verboselevel="${1}"
	local this_nrjobs="${2}"
	local this_logfile="${kcbench_logdir%%/}/${3}"
	local this_msgstart="${4}"

	echo "make O=${dir_outputtmp} -C ${dir_sources} -j ${this_nrjobs} vmlinux" > "${this_logfile}"
	kcbench_echo 1 4 "Running 'make O=${dir_outputtmp} -C ${dir_sources} -j ${this_nrjobs} vmlinux'"

	kcbench_echo 1 ${this_verboselevel} -n "${this_msgstart}"


	if /usr/bin/time -o "${this_logfile}.time" -f "P:%P R:%e U:%U S:%S" make O="${dir_outputtmp}" -C "${dir_sources}" -j ${this_nrjobs} vmlinux >> "${this_logfile}" 2>&1 ; then
		local time_points="$(echo 1000000/$(cut -d ' ' -f 2 < "${this_logfile}.time" | cut -d ':' -f 2) | /usr/bin/bc)"
		local time_details="$(cat "${this_logfile}.time")"
		kcbench_echo 1 ${this_verboselevel} "${time_points} (${time_details})"
	else
		kcbench_echo 2 1 "Failed ($(date))."

		if [[ "${savefailedlogs}" ]]; then
			# safe log and continue
			kcbench_echo 2 2 "Saving logfile to ${savefailedlogs}/kcbench-$(basename ${this_logfile})"
			cp "${this_logfile}" "${savefailedlogs}/kcbench-$(basename ${this_logfile})"
		elif [[ "${run_infinite}" ]]; then
			return 1
		else
			# what to do with the logfile?
			read -n 1 -s -t 300 -p "Hit 'l' within 300 seconds to view log-file." answer
			echo

			if [[ "${answer}" == [lL] ]]; then
				less "${this_logfile}" 
			fi

			# end
			kcbench_exit 2
		fi
	fi

	# cleanup
	kcbench_echo 1 3 "Cleaning up builddir"
	make O="${dir_outputtmp}" -C "${dir_sources}" -j ${default_number_of_jobs} clean &> "${kcbench_logdir}/make_clean"
}

# basic information about the system
kcebench_sysinfo()
{
	kcbench_echo 1 ${1} "Linux running:      $(uname -r)"
	kcbench_echo 1 ${1} "Compiler:           $(gcc --version | head -n 1)"
	kcbench_echo 1 ${1} "CPU:                $(grep '^processor' < /proc/cpuinfo  | wc -l) x $(grep 'model name' /proc/cpuinfo  | sed 's!model name\t: !!' | sort | uniq)"
	kcbench_echo 1 ${1} "Memory:             $(( $(awk '/MemTotal:/ { print $2}' /proc/meminfo) / 1024  )) MByte"
	kcbench_echo 1 ${1} "Linux compiled:     $(basename "${dir_sources}") (${dir_sources})"
}

myprog_help()
{
	echo "Usage: ${myprog_name} [options]"
	echo $'\n'"Compiles a kernel and messures the time it takes"
	echo $'\n'"Available options:"
	echo " --compiledir <path>      -- use <path>/kcbench for compile results (O=)"
	echo " --ignore-running-apps    -- Do not warn if cron or other daemons run"
	echo " --infinite               -- run endlessly"
	echo " --iterations <int>       -- number or iterations"
	echo " --jobs <int>             -- number of jobs to use ('make -j #') (*)"
	echo " --no-cachefill           -- omit the initial kernel compile to fill caches"
	echo " --verbose                -- increase verboselevel (*)"
	echo " --savefailedlogs <path>  -- save log of failed compile runs in <path>"
	echo " --src (<path>|<version>) -- take sources in <path> or from"
	echo "                             /usr/share/kcdata/linux-<version>"
	echo
	echo " --help                   -- this text"
	echo " --version                -- output program version"
	echo
	echo "(*) -- option can be past multiple times"
}


# set defaults which might get overwritten my command line parameters
kcbench_init


# parse cmdline options
while [ "${1}" ] ; do
	case "${1}" in
		--compiledir)
			shift
			dir_topoutput="${1}"
			shift
			;;
		--jobs)
			shift
			# without quotes, to make --jobs "4 8 16 32" possible
			number_of_jobs="${number_of_jobs} ${1}"
			shift
			;;
		--ignore-running-apps)
			shift
			ignore_running_apps="true"
			;;
		--infinite)
			shift
			run_infinite="true"
			;;
		--iterations)
			shift
			number_of_iterations="${1}"
			shift
			;;
		--no-cachefill)
			shift
			no_cachefill="true"
			;;
		--quiet)
			verboselevel="1"
			shift
			;;
		--savefailedlogs)
			shift
			savefailedlogs="${1}"
			shift
			;;
		--src)
			shift
			compile_srctree="${1}"
			shift
			;;
		--verbose)
			shift
			let verboselevel++
			;;
		--help)
			myprog_help
			exit 0
			;;
		--version)
			echo "${myprog_name} ${myprog_version}"
			exit 0
			;;
		--*)
			echo "Error: Unknown option '${1}'." >&2
			myprog_help >&2
			exit 2
			;;
		*)
			list_of_packages="${list_of_packages} ${1}"
			shift
			;;
	esac
done

# startup checks
kcbench_startupchecks

# go
kcbench_main

# cleanup
kcbench_exit

exit 0


--- NEW FILE kcbench-README ---
kcbench - Kernel compile benchmark 

## About

Kcbench compiles a Linux kernel to benchmark a system or test system stability


## Available options:

 --compiledir <path>      
   Use the subdirectory kcbench in <path>/ for compile results -- passes
   'O=<path> /kcbench/' to make when calling it to compile a kernel; use a
   tempdir if not given

 --ignore-running-apps
   Do not warn if cron or other daemons run in the background; the results
   might not be stable when those run and call jobs that consume CPU time or
   do a lot of I/O

 --infinite 
   run endlessly to test system stability

 --iterations <int>
   Number or iterations per number of jobs (default: 3)

 --jobs <int> 
   Number of jobs to use ('make -j #'); option can be given multiple times
   (default: number of CPUs * 2)

 --no-cachefill
   Omit the initial kernel compile to fill caches; saves time, but first
   result might be slightly lower then the following ones

 --verbose
   Increase verboselevel; option can be given multiple times

 --savefailedlogs <path> 
   Save log of failed compile runs in <path>

 --src (<path>|<version>) 
   Take sources in <path> or from /usr/share/kcdata/linux-<version>

 --help
   Show usage

 --version
   Output program version


## Examples:

 $ kcbench
   Takes newest kernel from /usr/share/kcdata/ and compiles three times

 $ kcbench--iterations 3 --jobs 2 --jobs 4
   Compile 3 times with 2 jobs and three times with 4 jobs


## Example output:

$ kcbench --iterations 2 --jobs 2 --jobs 4 --jobs 8 --ignore-running-apps 
Linux running:      2.6.23-0.222.rc9.git4.fc8
Compiler:           gcc (GCC) 4.1.2 20070925 (Red Hat 4.1.2-31)
CPU:                2 x Intel(R) Core(TM)2 CPU          6400  @ 2.13GHz
Memory:             1964 MByte
Linux compiled:     linux-2.6.20 (/usr/share/kcbench-data/linux-2.6.20)
Filling caches:     Done                                                      
Run 1 (-j 2):       5858 (P:195% R:170.70 U:263.51 S:69.42)
Run 2 (-j 2):       5830 (P:194% R:171.51 U:263.92 S:69.39)
Run 3 (-j 4):       5727 (P:193% R:174.60 U:267.12 S:70.42)
Run 4 (-j 4):       5779 (P:194% R:173.03 U:266.74 S:70.09)
Run 5 (-j 8):       5636 (P:191% R:177.43 U:270.14 S:70.39)
Run 6 (-j 8):       5607 (P:190% R:178.32 U:269.64 S:70.88)


## Results

In this example

 Run 1 (-j 4): 5775 (P:192% R:173.15 U:263.49 S:69.42)

is has taken 173.15 seconds real time (R) to compile the kernel; the CPU-Usage
(P) was 192 percent; user time (U) spend was 296.49 and sys time (S) 69.42.

As most people prefer if higher numbers mean faster systems -- to give them
what they expect kcbench divides 1000000 by the real time spend, which results
in 5775 kcbench points (1000000/173.15) in this example. 


## Usage hints

 * sometimes using exactly as much jobs as processors in the system results in
   the a result faster than the default (two times the number of processors)

 * the compiler has a huge impact on the results; if you compare results from
   different machines make sure they use the same one

 * the kernel that is being compiled of course has a huge impact as well;
   compare only results where you compiled the same kernel version


## EOF


--- NEW FILE kcbench.spec ---
Name:           kcbench
Version:        0.1
Release:        2
Summary:        Kernel compile benchmark

Group:          Applications/System
License:        MIT
URL:            http://fedoraproject.org/wiki/Packages/kcbench
Source0:        kcbench
Source1:        %{name}-README

BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildArch:      noarch

# data we compile; no need for a specific version; 
Requires:       kcbench-datafiles
# needed for compiling a kernel:
Requires:       make gcc binutils
# needed for kcbench
Requires:       %{_bindir}/time %{_bindir}/bc

%description
Compiles a linux kernel to benchmark a system or test system stability.


%prep
%setup -q -c -T
echo "Nothing to prep"


%build
echo "Nothing to build"


%install
rm -rf ${RPM_BUILD_ROOT}
install -D -p -m 0755 %{SOURCE0} ${RPM_BUILD_ROOT}%{_bindir}/kcbench
install -D -p -m 0644 %{SOURCE1} ./README


%clean
rm -rf ${RPM_BUILD_ROOT}


%files
%defattr(-,root,root,-)
%doc README
%{_bindir}/kcbench


%changelog
* Sat Oct 13 2007 Thorsten Leemhuis <fedora[AT]leemhuis[DOT]org> - 0.1-2
- require make gcc and binutils, needed for kernel compile
- require /usr/bin/{time,bc} for kcbench
- include a README file

* Mon Oct 01 2007 Thorsten Leemhuis <fedora[AT]leemhuis[DOT]org> - 0.1-1
- initial package




More information about the fedora-extras-commits mailing list