Import BSDDB 4.7.25 (as of svn r89086)

This commit is contained in:
Zachary Ware
2017-09-04 13:40:25 -05:00
parent 4b29e0458f
commit 8f590873d0
4781 changed files with 2241032 additions and 6 deletions

84
test_micro/README Normal file
View File

@@ -0,0 +1,84 @@
# $Id: README,v 1.6 2007/12/21 19:22:01 bostic Exp $
A simple framework for core Berkeley DB micro-benchmarks, intended for
two purposes: to certify a port of Berkeley DB to a new platform, and
to provide micro-benchmark information between different Berkeley DB
releases.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
To run the tests:
1. Unpack and build the Berkeley DB releases you want to run against.
(Note that test_micro is only known to work on release 4.0 and later.)
2. Run the tests:
% sh test_micro
By default, tests are run for all of the Berkeley DB builds found in
the current working directory. A build is identified by its
top-level name, and is expected to be of the form:
db-<major>.<minor>.<patch>
and the fact the Berkeley DB library has been built in the standard
location in that directory tree (for example, "build_unix/libdb.a".
Directories with other names and directories without a library will
be ignored.
You can run a subset of the tests using command-line arguments:
% sh test_micro 3 # Run test 3
% sh test_micro 3-5 # Run tests 3-5
% sh test_micro 3- # Run test 3 to the maximum test
% sh test_micro -3 # Run tests 1-3
You can run on a subset of the releases using the MAJOR and MINOR
environment variables:
% env MAJOR=4 MINOR=2 sh test_micro # Run on 4.2.XX
# Run on 4.1.XX and 4.2.XX
% env MAJOR=4 MINOR='[12]' sh test_micro
3. If you want to generate the micro-benchmark output build the HTML
page after the run:
% sh report
The output of the tests and the web page are created in the directory
RUN.hostname (for example, "RUN.abyssinian"). The tests are numeric
filenames in that directory (for example, "1", "2", "36"). The web
page output is in the file "hostname.html".
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
To run different test configurations:
1. Modify the configuration files in the configs/ directory to run the
tests you want to run. The configuration file configs/run.std is the
tests that are run by the test_micro shell script.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
To add a new test program:
1. Add a new file to the SOURCE directory, and build it as part of
building the test_micro program. This will require changes to
the test_micro shell script, as well as the standard build rules
for all of the Berkeley DB systems, found in the dist/ directory.
The file must output the following line on stdout:
# title
major.minor.patch<tab>operations/second
For example:
# 10000 Btree database open/close pairs
3.0.55 29600.69
3.1.17 30438.25
2. Modify the file test_micro/test_micro.c to exec your new command
(this should only require changing the cmdlist structure at the top
of that file).
3. Modify the test_micro configuration files in the configs/ directory
to run your new command.

View File

@@ -0,0 +1,115 @@
b_curalloc -c 100
b_curwalk -c 10 -d 10 -Ss -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -Ss -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -p -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -p -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -pSs -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -pSs -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -ps -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -ps -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -s -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -s -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 100 -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 100 -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 10 -d 10 -s -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 100 -d 10 -s -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 100 -d 10 -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 100 -d 10 -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 100 -p -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 100 -p -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 100 -p -t queue -w 10 -C 524288 -P 1024
b_curwalk -c 100 -p -t recno -w 10 -C 524288 -P 1024
b_curwalk -c 100 -t btree -w 10 -C 524288 -P 1024
b_curwalk -c 100 -t hash -w 10 -C 524288 -P 1024
b_curwalk -c 100 -t queue -w 10 -C 524288 -P 1024
b_curwalk -c 100 -t recno -w 10 -C 524288 -P 1024
b_del -c 100 -t btree -C 524288
b_del -c 100 -t hash -C 524288
b_del -c 100 -t queue -C 524288
b_del -c 100 -t recno -C 524288
b_del -w -c 100 -t btree -C 524288
b_del -w -c 100 -t hash -C 524288
b_del -w -c 100 -t queue -C 524288
b_del -w -c 100 -t recno -C 524288
b_get -c 100 -t btree -C 524288
b_get -c 100 -t hash -C 524288
b_get -c 100 -t queue -C 524288
b_get -c 100 -t recno -C 524288
b_inmem -d 32 -k 8 -o 10 -P 1024 -C 524288 bulk
b_inmem -d 32 -k 8 -o 10 -P 1024 -C 524288 txn-sync
b_inmem -d 32 -k 8 -o 10 -P 1024 -C 524288 read
b_inmem -d 32 -k 8 -o 100 -P 1024 -C 524288 txn-nosync
b_inmem -d 32 -k 8 -o 100 -P 1024 -C 524288 txn-read
b_inmem -d 32 -k 8 -o 100 -P 1024 -C 524288 txn-write
b_inmem -d 32 -k 8 -o 100 -P 1024 -C 524288 txn-write-nosync
b_inmem -d 32 -k 8 -o 100 -P 1024 -C 524288 write
b_load -c 100 -t hash -C 524288
b_load -c 100 -t btree -C 524288
b_load -c 100 -t queue -C 524288
b_load -c 100 -t recno -C 524288
b_load -d -c 100 -t btree -C 524288
b_load -d -c 100 -t hash -C 524288
b_open -c 100 -d -t btree
b_open -c 100 -d -t hash
b_open -c 100 -d -t queue
b_open -c 100 -d -t recno
b_open -c 100 -f -t btree
b_open -c 100 -f -t hash
b_open -c 100 -f -t queue
b_open -c 100 -f -t recno
b_open -c 100 -fd -t btree
b_open -c 100 -fd -t hash
b_open -c 100 -fd -t recno
b_open -c 100 -t btree
b_open -c 100 -t hash
b_open -c 100 -t queue
b_open -c 100 -t recno
b_put -c 10 -d 64 -t btree -C 524288
b_put -c 10 -d 64 -t hash -C 524288
b_put -c 10 -d 64 -t recno -C 524288
b_put -c 100 -s 10 -t btree -C 524288
b_put -c 100 -s 10 -t hash -C 524288
b_put -c 100 -s 10 -t queue -C 524288
b_put -c 100 -s 10 -t recno -C 524288
b_put -c 100 -t btree -C 524288
b_put -c 100 -t hash -C 524288
b_put -c 100 -t queue -C 524288
b_put -c 100 -t recno -C 524288
b_recover -c 100 -C 524288
b_txn -a -c 100
b_txn -c 100
b_txn_write -a -c 100
b_txn_write -ar -c 100
b_txn_write -c 100
b_txn_write -r -c 100
b_txn_write -rw -c 100
b_txn_write -w -c 100
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t btree
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t hash
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t btree
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t hash
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t btree
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t hash
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t btree
b_workload -w A -c 100 -g 10 -d 20 -p 1024 -t hash
b_workload -w A -c 100 -g 10 -d 256 -p 1024 -t btree
b_workload -w A -c 100 -g 10 -d 256 -p 1024 -t hash
b_workload -w A -c 100 -g 10 -o -t btree -p 1024
b_workload -w A -c 100 -g 10 -o -t hash -p 1024
b_workload -w E -c 100 -g 10 -d 20 -p 1024 -t btree
b_workload -w E -c 100 -g 10 -d 20 -p 1024 -t hash
b_workload -w F -c 100 -g 10 -d 20 -p 1024 -t btree
b_workload -w F -c 100 -g 10 -d 20 -p 1024 -t hash
b_workload -w G -c 100 -g 10 -d 20 -p 1024 -t btree
b_workload -w G -c 100 -g 10 -d 20 -p 1024 -t hash
b_workload -w H -c 100 -d 20 -p 1024 -t hash

116
test_micro/configs/run.std Normal file
View File

@@ -0,0 +1,116 @@
b_curalloc -c 1000000
b_curwalk -c 100 -d 1000 -Ss -t btree -w 100
b_curwalk -c 100 -d 1000 -Ss -t hash -w 100
b_curwalk -c 100 -d 1000 -p -t btree -w 100
b_curwalk -c 100 -d 1000 -p -t hash -w 100
b_curwalk -c 100 -d 1000 -pSs -t btree -w 100
b_curwalk -c 100 -d 1000 -pSs -t hash -w 100
b_curwalk -c 100 -d 1000 -ps -t btree -w 100
b_curwalk -c 100 -d 1000 -ps -t hash -w 100
b_curwalk -c 100 -d 1000 -s -t btree -w 100
b_curwalk -c 100 -d 1000 -s -t hash -w 100
b_curwalk -c 100 -d 1000 -t btree -w 100
b_curwalk -c 100 -d 1000 -t hash -w 100
b_curwalk -c 10000 -d 10 -s -t btree -w 100
b_curwalk -c 10000 -d 10 -s -t hash -w 100
b_curwalk -c 10000 -d 10 -t btree -w 100
b_curwalk -c 10000 -d 10 -t hash -w 100
b_curwalk -c 100000 -p -t btree -w 100
b_curwalk -c 100000 -p -t hash -w 100
b_curwalk -c 100000 -p -t queue -w 100
b_curwalk -c 100000 -p -t recno -w 100
b_curwalk -c 100000 -t btree -w 100
b_curwalk -c 100000 -t hash -w 100
b_curwalk -c 100000 -t queue -w 100
b_curwalk -c 100000 -t recno -w 100
b_del -c 100000 -t btree
b_del -c 100000 -t hash
b_del -c 100000 -t queue
b_del -c 100000 -t recno
b_del -w -c 100000 -t btree
b_del -w -c 100000 -t hash
b_del -w -c 100000 -t queue
b_del -w -c 100000 -t recno
b_get -c 1000000 -t btree
b_get -c 1000000 -t hash
b_get -c 1000000 -t queue
b_get -c 1000000 -t recno
b_inmem -d 32 -k 8 -o 100000 -P 32768 bulk
b_inmem -d 32 -k 8 -o 100000 -P 32768 txn-sync
b_inmem -d 32 -k 8 -o 1000000 -P 32768 read
b_inmem -d 32 -k 8 -o 1000000 -P 32768 txn-nosync
b_inmem -d 32 -k 8 -o 1000000 -P 32768 txn-read
b_inmem -d 32 -k 8 -o 1000000 -P 32768 txn-write
b_inmem -d 32 -k 8 -o 1000000 -P 32768 txn-write-nosync
b_inmem -d 32 -k 8 -o 1000000 -P 32768 write
b_load -c 100000 -t hash
b_load -c 1000000 -t btree
b_load -c 1000000 -t queue
b_load -c 1000000 -t recno
b_load -d -c 1000000 -t btree
b_load -d -c 1000000 -t hash
b_open -c 10000 -d -t btree
b_open -c 10000 -d -t hash
b_open -c 10000 -d -t queue
b_open -c 10000 -d -t recno
b_open -c 10000 -f -t btree
b_open -c 10000 -f -t hash
b_open -c 10000 -f -t queue
b_open -c 10000 -f -t recno
b_open -c 10000 -fd -t btree
b_open -c 10000 -fd -t hash
b_open -c 10000 -fd -t recno
b_open -c 10000 -t btree
b_open -c 10000 -t hash
b_open -c 10000 -t queue
b_open -c 10000 -t recno
b_put -c 100000 -d 204800 -t btree
b_put -c 100000 -d 204800 -t hash
b_put -c 100000 -d 204800 -t recno
b_put -c 1000000 -s 10 -t btree
b_put -c 1000000 -s 10 -t hash
b_put -c 1000000 -s 10 -t queue
b_put -c 1000000 -s 10 -t recno
b_put -c 1000000 -t btree
b_put -c 1000000 -t hash
b_put -c 1000000 -t queue
b_put -c 1000000 -t recno
b_recover -c 1000000
b_txn -a -c 1000000
b_txn -c 1000000
b_txn_write -a -c 100000
b_txn_write -ar -c 100000
b_txn_write -c 10000
b_txn_write -r -c 10000
b_txn_write -rw -c 100000
b_txn_write -w -c 100000
b_workload -w A -c 100000 -g 10 -d 20 -p 1024 -t btree
b_workload -w A -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -w A -c 100000 -g 10 -d 20 -p 32768 -t btree
b_workload -w A -c 100000 -g 10 -d 20 -p 32768 -t hash
b_workload -w A -c 100000 -g 10 -d 20 -p 4096 -t btree
b_workload -w A -c 100000 -g 10 -d 20 -p 4096 -t hash
b_workload -w A -c 100000 -g 10 -d 20 -p 8192 -t btree
b_workload -w A -c 100000 -g 10 -d 20 -p 8192 -t hash
b_workload -w A -c 100000 -g 10 -d 256 -p 1024 -t btree
b_workload -w A -c 100000 -g 10 -d 256 -p 1024 -t hash
b_workload -w A -c 100000 -o -t btree
b_workload -w A -c 100000 -o -t hash
b_workload -w E -c 100000 -g 10 -d 20 -p 1024 -t btree
b_workload -w E -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -w F -c 100000 -g 10 -d 20 -p 1024 -t btree
b_workload -w F -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -w G -c 100000 -g 10 -d 20 -p 1024 -t btree
b_workload -w G -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -w H -c 10000000 -d 20 -p 1024 -t hash

View File

@@ -0,0 +1,38 @@
b_workload -m 1 -w A -v -c 100000 -o -t hash
b_workload -m 2 -w A -v -c 100000 -o -t btree
b_workload -m 3 -w A -v -c 100000 -g 10 -d 20 -p 32768 -t hash
b_workload -m 4 -w A -v -c 100000 -g 10 -d 20 -p 32768 -t btree
b_workload -m 5 -w A -v -c 100000 -g 10 -d 20 -p 8192 -t hash
b_workload -m 6 -w A -v -c 100000 -g 10 -d 20 -p 8192 -t btree
b_workload -m 7 -w A -v -c 100000 -g 10 -d 20 -p 4096 -t hash
b_workload -m 8 -w A -v -c 100000 -g 10 -d 20 -p 4096 -t btree
b_workload -m 9 -w A -v -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -m 10 -w A -v -c 100000 -g 10 -d 20 -p 1024 -t btree
b_workload -m 11 -w A -v -c 10000 -g 10 -d 256 -p 1024 -t hash
b_workload -m 12 -w A -v -c 10000 -g 10 -d 256 -p 1024 -t btree
b_workload -m 13 -w F -v -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -m 14 -w F -v -c 100000 -g 10 -d 20 -p 1024 -t btree
b_workload -m 15 -w G -v -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -m 16 -w G -v -c 100000 -g 10 -d 20 -p 1024 -t btree
# Run put/get(G) with different page sizes, since fill factor
# is interesting when not deleting all of the elements.
b_workload -m 17 -w E -v -c 100000 -g 10 -d 20 -p 32768 -t hash
b_workload -m 18 -w E -v -c 100000 -g 10 -d 20 -p 32768 -t btree
b_workload -m 19 -w E -v -c 100000 -g 10 -d 20 -p 8192 -t hash
b_workload -m 20 -w E -v -c 100000 -g 10 -d 20 -p 8192 -t btree
b_workload -m 21 -w E -v -c 100000 -g 10 -d 20 -p 4096 -t hash
b_workload -m 22 -w E -v -c 100000 -g 10 -d 20 -p 4096 -t btree
b_workload -m 23 -w E -v -c 100000 -g 10 -d 20 -p 1024 -t hash
b_workload -m 24 -w E -v -c 100000 -g 10 -d 20 -p 1024 -t btree
b_workload -m 25 -w E -v -c 10000 -g 10 -d 256 -p 1024 -t hash
b_workload -m 26 -w E -v -c 10000 -g 10 -d 256 -p 1024 -t btree
b_workload -m 27 -w E -v -c 100000 -g 10 -o -d 10 -p 1024 -t hash
b_workload -m 28 -w E -v -c 100000 -g 10 -o -d 10 -p 1024 -t btree
b_workload -m 29 -w A -v -c 10000 -g 10 -d 1024 -p 512 -t hash
b_workload -m 30 -w A -v -c 10000 -g 10 -d 1024 -p 512 -t btree
b_workload -m 31 -w H -v -c 1000000 -d 20 -p 8192 -t hash
b_workload -m 32 -w H -v -c 1000000 -d 20 -p 8192 -t btree
b_workload -m 33 -w H -v -c 1000000 -d 20 -p 512 -t hash
b_workload -m 34 -w H -v -c 1000000 -d 20 -p 512 -t btree
b_workload -m 35 -w H -v -c 10000000 -d 20 -p 512 -t hash
b_workload -m 36 -w H -v -c 10000000 -d 20 -p 512 -t btree

117
test_micro/report Normal file
View File

@@ -0,0 +1,117 @@
#! /bin/sh
#
# $Id: report,v 1.7 2008/02/07 18:11:34 bostic Exp $
# Use our pathname to locate the absolute path for our awk scripts.
t=`dirname $0`
h=`(cd $t && echo $PWD)`
# We need a temporary file, and we need to clean it up after failure.
tmp="$PWD/__t"
trap 'rm -f $tmp; exit 1' 1 2 3 13 15
trap 'rm -f $tmp; exit 0' 0
# header --
# Output HTML page header.
# $1: directory name.
header()
{
echo "<html>"
echo "<head>"
machine=`echo $1 | sed 's/.*\.//'`
echo "<title>Berkeley DB test_micro run: $machine</title>"
echo "</head>"
echo "<body bgcolor=white>"
echo "<center><h1>Berkeley DB test_micro run: $machine</h1></center>"
echo "<p align=right>`date`</p>"
test -f UNAME && cat UNAME
}
# footer --
# Output HTML page footer.
footer()
{
echo "</body>"
echo "</html>"
}
# table --
# Create a table.
# $1: output file
table()
{
title="Test $1: `egrep '^#' $1 | sort -u | sed 's/^#[ ]*//'`"
echo "<hr size=1 noshade>"
echo "<table cellspacing=0 cellpadding=0 border=0>"
echo "<th align=left colspan=2>$title</th>"
echo "<tr>"
echo "<th align=right>Release</th>"
echo "<th align=center>Operations/second</th>"
echo "</tr>"
# You can set the MAJOR and MINOR environment variables to limit
# the BDB releases for which a report is created.
#
# Process the output into a single line per release.
egrep "^${MAJOR:-[0-9][0-9]*}.${MINOR:-*}" $1 |
awk -f $h/report.awk |
sort -n > $tmp
# Get the release count, and maximum value.
nrel=`wc -l $tmp`
max=`sort -k 2 -n -t ":" < $tmp | tail -1 | awk -F: '{print $2}'`
# Display the output.
IFS=":"
cat $tmp | while true; do
# release, average, runs, percent, standard deviation
read rel avg runs percent rsd
if test "X$rel" = "X" ; then
break;
fi
# echo "read: rel $rel, avg $avg, runs $runs, percent $percent, rsd $rsd" > /dev/stderr
echo "<tr>"
echo "<td align=right width=80><pre>$rel</pre></td>"
echo "<td>"
echo "<table>"
echo "<tr>"
t=`echo "400 * ($avg/($max + $max/10))" | bc -l`
t=`printf %.0f $t`
echo "<td bgcolor='#003366' width=$t>&nbsp;</td>"
t=`echo "400 - $t" | bc`
echo "<td bgcolor='#CCCCCC' width=$t>&nbsp;</td>"
echo "<td>&nbsp;&nbsp;</td>"
echo "<td align=right width=100><pre>$avg</pre></td>"
if test "X$percent" != "X" -o "X$rsd" != "X"; then
echo -n "<td align=right><pre>&nbsp;&nbsp;("
if test "X$percent" = "X"; then
echo -n '***'
else
echo -n "-$percent"
fi
if test "X$rsd" != "X"; then
echo -n ", $rsd rsd, $runs runs"
fi
echo ")</pre></td>"
fi
echo "</tr>"
echo "</table>"
echo "</tr>"
done
echo "</table>"
}
for i in RUN.*; do
echo "Building $i..."
name=`echo $i | sed 's/RUN.//'`
(cd $i
header $i
for j in `ls [0-9]* | sort -n`; do
table $j
done
footer) > $i/$name.html
done
exit 0

40
test_micro/report.awk Normal file
View File

@@ -0,0 +1,40 @@
# $Id: report.awk,v 1.3 2008/01/02 15:54:03 bostic Exp $
/^[^#]/ {
total[$1] += $2
sum[$1] += $2 * $2
++count[$1];
}
END {
# Compute the average, find the maximum.
for (i in total) {
avg[i] = total[i] / count[i];
if (max < avg[i])
max = avg[i]
}
for (i in total) {
# Calculate variance by raw score method.
var = (sum[i] - ((total[i] * total[i]) / count[i])) / count[i];
# The standard deviation is the square root of the variance.
stdv = sqrt(var);
# Display the release value, the average score, and run count.
printf("%s:%.2f:%d:", i, avg[i], count[i]);
# If this run wasn't the fastest, display the percent by which
# this run was slower.
if (max != avg[i])
printf("%.0f%%", ((max - avg[i]) / max) * 100);
printf(":");
# If there was more than a single run, display the relative
# standard deviation.
if (count[i] > 1)
printf("%.0f%%", stdv * 100 / avg[i]);
printf("\n");
}
}

101
test_micro/source/LIST Normal file
View File

@@ -0,0 +1,101 @@
Test list:
b_curalloc
Cursor allocation
usage: b_curalloc [-c count]
-c Cursor count
b_curwalk
Walk a cursor through N records
usage: b_curwalk [-pSs] [-C cachesz]
[-c cnt] [-d dupcnt] [-P pagesz] [-t type] [-w walkcnt]
-C Cache size
-c Record count
-d Duplicate record count
-P Page size
-p Walk backward instead of forward
-S Skip duplicates
-s Sort duplicates
-t Database type (B | H | Q | R)
b_del
Delete records
usage: b_del [-w] [-C cachesz] [-c count] [-t type]
-C Cache size
-c Record count
-t Database type (B | H | Q | R)
-w Delete through cursor
b_get
Read records
usage: b_get [-C cachesz] [-c count] [-t type]
-C Cache size
-c Record count
-t Database type (B | H | Q | R)
b_load
Insert records
usage: b_load [-d] [-C cachesz] [-c count] [-t type]
-C Cache size
-c Record count
-d Use duplicate records
-t Database type (B | H | Q | R)
b_open
Database open/close
usage: b_open [-df] [-c count] [-t type]
-d Open/close a subdatabase
-f Open/close a physical file
-c Open/close count
-t Database type (B | H | Q | R)
b_put
Overwrite record
usage: b_put [-C cachesz]
[-c count] [-d bytes] [-s secondaries] [-t type]
-C Cache size
-c Record count
-d Data size
-s Number of secondaries
-t Database type (B | H | Q | R)
b_recover
Run recovery
usage: b_recover [-C cachesz] [-c count]
-C Cache size
-c Transactions to recover
b_txn
Abort or commit a transaction containing no operations
usage: b_txn [-a] [-c count]
-a Abort rather than commit
-c Transaction count
b_txn_write
Write/commit transaction
usage: b_txn_write [-arw] [-c count]
-a nosync
-c Transaction count
-r Configure replication stub callback
-w write-nosync
b_workload

View File

@@ -0,0 +1,65 @@
/*
* $Id: b_curalloc.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_curalloc(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBC *curp;
int ch, i, count;
count = 100000;
while ((ch = getopt(argc, argv, "c:")) != EOF)
switch (ch) {
case 'c':
count = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
dbp->set_errfile(dbp, stderr);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#endif
/* Allocate a cursor count times. */
TIMER_START;
for (i = 0; i < count; ++i) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &curp, 0) == 0);
DB_BENCH_ASSERT(curp->c_close(curp) == 0);
}
TIMER_STOP;
printf("# %d cursor allocations\n", count);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_curalloc [-c count]\n");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,204 @@
/*
* $Id: b_curwalk.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_curwalk(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBTYPE type;
DBC *dbc;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize, pagesize, walkflags;
int ch, i, count, dupcount, j;
int prev, ret, skipdupwalk, sorted, walkcount;
char *ts, dbuf[32], kbuf[32];
type = DB_BTREE;
cachesize = 10 * MEGABYTE;
pagesize = 16 * 1024;
count = 100000;
dupcount = prev = skipdupwalk = sorted = 0;
walkcount = 1000;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:d:P:pSst:w:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 'd':
dupcount = atoi(optarg);
break;
case 'P':
pagesize = (u_int32_t)atoi(optarg);
break;
case 'p':
prev = 1;
break;
case 'S':
skipdupwalk = 1;
break;
case 's':
sorted = 1;
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case 'w':
walkcount = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/*
* Queue and Recno don't support duplicates.
*/
if (dupcount != 0 && (type == DB_QUEUE || type == DB_RECNO)) {
fprintf(stderr,
"b_curwalk: Queue and Recno don't support duplicates\n");
return (usage());
}
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
#define DB_PREV_NODUP 0
/*
* DB_PREV_NODUP wasn't available until after 3.0.55.
*
* For some reason, testing sorted duplicates doesn't work either.
* I don't really care about 3.0.55 any more, just ignore it.
*/
return (0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0);
/* Set duplicates flag. */
if (dupcount != 0)
DB_BENCH_ASSERT(
dbp->set_flags(dbp, sorted ? DB_DUPSORT : DB_DUP) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* Insert count in-order key/data pairs. */
data.data = dbuf;
data.size = 20;
if (type == DB_BTREE || type == DB_HASH) {
key.size = 10;
key.data = kbuf;
for (i = 0; i < count; ++i) {
(void)snprintf(kbuf, sizeof(kbuf), "%010d", i);
for (j = 0; j <= dupcount; ++j) {
(void)snprintf(dbuf, sizeof(dbuf), "%020d", j);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
}
} else {
key.data = &recno;
key.size = sizeof(recno);
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
walkflags = prev ?
(skipdupwalk ? DB_PREV_NODUP : DB_PREV) :
(skipdupwalk ? DB_NEXT_NODUP : DB_NEXT);
/* Walk the cursor through the tree N times. */
TIMER_START;
for (i = 0; i < walkcount; ++i) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while ((ret = dbc->c_get(dbc, &key, &data, walkflags)) == 0)
;
DB_BENCH_ASSERT(ret == DB_NOTFOUND);
DB_BENCH_ASSERT(dbc->c_close(dbc) == 0);
}
TIMER_STOP;
printf("# %d %s %s cursor of %d 10/20 byte key/data items",
walkcount, ts, prev ?
(skipdupwalk ? "DB_PREV_NODUP" : "DB_PREV") :
(skipdupwalk ? "DB_NEXT_NODUP" : "DB_NEXT"),
count);
if (dupcount != 0)
printf(" with %d dups", dupcount);
printf("\n");
/*
* An "operation" is traversal of a single key/data pair -- not a
* return of the key/data pair, since some versions of this test
* skip duplicate key/data pairs.
*
* Use a "double" so we don't overflow.
*/
TIMER_DISPLAY((double)count * walkcount);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (EXIT_SUCCESS);
}
static int
usage()
{
(void)fprintf(stderr, "%s\n\t%s\n",
"usage: b_curwalk [-pSs] [-C cachesz]",
"[-c cnt] [-d dupcnt] [-P pagesz] [-t type] [-w walkcnt]");
return (EXIT_FAILURE);
}

162
test_micro/source/b_del.c Normal file
View File

@@ -0,0 +1,162 @@
/*
* $Id: b_del.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_del(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBC *dbc;
DBT key, data;
DBTYPE type;
db_recno_t recno;
u_int32_t cachesize;
int ch, i, count, ret, use_cursor;
char *ts, buf[32];
type = DB_BTREE;
cachesize = MEGABYTE;
count = 100000;
use_cursor = 0;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:t:w")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case 'w':
use_cursor = 1;
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
data.data = "01234567890123456789";
data.size = 20;
/* Store a key/data pair. */
switch (type) {
case DB_BTREE:
case DB_HASH:
key.data = buf;
key.size = 10;
break;
case DB_QUEUE:
case DB_RECNO:
key.data = &recno;
key.size = sizeof(recno);
break;
case DB_UNKNOWN:
b_util_abort();
break;
}
/* Insert count in-order key/data pairs. */
if (type == DB_BTREE || type == DB_HASH)
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%010d", i);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
else
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
/* Delete the records. */
TIMER_START;
if (use_cursor) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while ((ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0)
DB_BENCH_ASSERT(dbc->c_del(dbc, 0) == 0);
DB_BENCH_ASSERT (ret == DB_NOTFOUND);
} else
if (type == DB_BTREE || type == DB_HASH)
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%010d", i);
DB_BENCH_ASSERT(
dbp->del(dbp, NULL, &key, 0) == 0);
}
else
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->del(dbp, NULL, &key, 0) == 0);
TIMER_STOP;
printf(
"# %d %s database in-order delete of 10/20 byte key/data pairs using %s\n",
count, ts, use_cursor ? "a cursor" : "the key");
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_del [-w] [-C cachesz] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

129
test_micro/source/b_get.c Normal file
View File

@@ -0,0 +1,129 @@
/*
* $Id: b_get.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_get(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBTYPE type;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize;
int ch, i, count;
char *ts;
type = DB_BTREE;
cachesize = MEGABYTE;
count = 100000;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:t:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 10) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Store a key/data pair. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
switch (type) {
case DB_BTREE:
case DB_HASH:
key.data = "aaaaa";
key.size = 5;
break;
case DB_QUEUE:
case DB_RECNO:
recno = 1;
key.data = &recno;
key.size = sizeof(recno);
break;
case DB_UNKNOWN:
b_util_abort();
break;
}
data.data = "bbbbb";
data.size = 5;
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
/* Retrieve the key/data pair count times. */
TIMER_START;
for (i = 0; i < count; ++i)
DB_BENCH_ASSERT(dbp->get(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
printf("# %d %s database get of cached key/data item\n", count, ts);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_get [-C cachesz] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

423
test_micro/source/b_inmem.c Normal file
View File

@@ -0,0 +1,423 @@
/*
* $Id: b_inmem.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0
/*
* The in-memory tests don't run on early releases of Berkeley DB.
*/
#undef MEGABYTE
#define MEGABYTE (1024 * 1024)
u_int32_t bulkbufsize = 4 * MEGABYTE;
u_int32_t cachesize = 32 * MEGABYTE;
u_int32_t datasize = 32;
u_int32_t keysize = 8;
u_int32_t logbufsize = 8 * MEGABYTE;
u_int32_t numitems;
u_int32_t pagesize = 32 * 1024;
FILE *fp;
char *progname;
static void op_ds __P((u_int, int));
static void op_ds_bulk __P((u_int, u_int *));
static void op_tds __P((u_int, int, u_int32_t, u_int32_t));
static int usage __P((void));
static void
op_ds(u_int ops, int update)
{
DB_ENV *dbenv;
char *letters = "abcdefghijklmnopqrstuvwxuz";
DB *dbp;
DBT key, data;
char *keybuf, *databuf;
DB_MPOOL_STAT *gsp;
DB_BENCH_ASSERT((keybuf = malloc(keysize)) != NULL);
DB_BENCH_ASSERT((databuf = malloc(datasize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
memset(keybuf, 'a', keysize);
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
dbenv = dbp->dbenv;
dbp->set_errfile(dbp, stderr);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
if (update) {
TIMER_START;
for (; ops > 0; --ops) {
keybuf[(ops % keysize)] = letters[(ops % 26)];
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
TIMER_STOP;
} else {
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
TIMER_START;
for (; ops > 0; --ops)
DB_BENCH_ASSERT(
dbp->get(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
}
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_cache_miss == 0);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
}
static void
op_ds_bulk(u_int ops, u_int *totalp)
{
DB_ENV *dbenv;
DB *dbp;
DBC *dbc;
DBT key, data;
u_int32_t len, klen;
u_int i, total;
char *keybuf, *databuf;
void *pointer, *dp, *kp;
DB_MPOOL_STAT *gsp;
DB_BENCH_ASSERT((keybuf = malloc(keysize)) != NULL);
DB_BENCH_ASSERT((databuf = malloc(bulkbufsize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
dbenv = dbp->dbenv;
dbp->set_errfile(dbp, stderr);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 1) == 0);
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
for (i = 1; i <= numitems; ++i) {
(void)snprintf(keybuf, keysize, "%7d", i);
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
#if 0
fp = fopen("before", "w");
dbp->set_msgfile(dbp, fp);
DB_BENCH_ASSERT (dbp->stat_print(dbp, DB_STAT_ALL) == 0);
#endif
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
data.ulen = bulkbufsize;
data.flags = DB_DBT_USERMEM;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
TIMER_START;
for (total = 0; ops > 0; --ops) {
DB_BENCH_ASSERT(dbc->c_get(
dbc, &key, &data, DB_FIRST | DB_MULTIPLE_KEY) == 0);
DB_MULTIPLE_INIT(pointer, &data);
while (pointer != NULL) {
DB_MULTIPLE_KEY_NEXT(pointer, &data, kp, klen, dp, len);
if (kp != NULL)
++total;
}
}
TIMER_STOP;
*totalp = total;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_cache_miss == 0);
#if 0
fp = fopen("before", "w");
dbp->set_msgfile(dbp, fp);
DB_BENCH_ASSERT (dbp->stat_print(dbp, DB_STAT_ALL) == 0);
#endif
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
COMPQUIET(dp, NULL);
COMPQUIET(klen, 0);
COMPQUIET(len, 0);
}
static void
op_tds(u_int ops, int update, u_int32_t env_flags, u_int32_t log_flags)
{
DB *dbp;
DBT key, data;
DB_ENV *dbenv;
DB_MPOOL_STAT *gsp;
DB_TXN *txn;
char *keybuf, *databuf;
DB_BENCH_ASSERT((keybuf = malloc(keysize)) != NULL);
DB_BENCH_ASSERT((databuf = malloc(datasize)) != NULL);
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = keybuf;
key.size = keysize;
memset(keybuf, 'a', keysize);
data.data = databuf;
data.size = datasize;
memset(databuf, 'b', datasize);
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
/* General environment configuration. */
#ifdef DB_AUTO_COMMIT
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, DB_AUTO_COMMIT, 1) == 0);
#endif
if (env_flags != 0)
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, env_flags, 1) == 0);
/* Logging configuration. */
if (log_flags != 0)
#if DB_VERSION_MINOR >= 7
DB_BENCH_ASSERT(
dbenv->log_set_config(dbenv, log_flags, 1) == 0);
#else
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, log_flags, 1) == 0);
#endif
#ifdef DB_LOG_INMEMORY
if (!(log_flags & DB_LOG_INMEMORY))
#endif
#ifdef DB_LOG_IN_MEMORY
if (!(log_flags & DB_LOG_IN_MEMORY))
#endif
DB_BENCH_ASSERT(dbenv->set_lg_max(dbenv, logbufsize * 10) == 0);
DB_BENCH_ASSERT(dbenv->set_lg_bsize(dbenv, logbufsize) == 0);
DB_BENCH_ASSERT(dbenv->open(dbenv, "TESTDIR",
DB_CREATE | DB_PRIVATE | DB_INIT_LOCK |
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0666) == 0);
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
DB_BENCH_ASSERT(dbp->set_pagesize(dbp, pagesize) == 0);
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
if (update) {
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
TIMER_START;
for (; ops > 0; --ops)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_page_out == 0);
} else {
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
(void)dbenv->memp_stat(dbenv, &gsp, NULL, DB_STAT_CLEAR);
TIMER_START;
for (; ops > 0; --ops) {
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(
dbp->get(dbp, NULL, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
}
TIMER_STOP;
(void)dbenv->memp_stat(dbenv, &gsp, NULL, 0);
DB_BENCH_ASSERT(gsp->st_cache_miss == 0);
}
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
}
#define DEFAULT_OPS 1000000
int
b_inmem(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
u_int ops, total;
int ch;
if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
else
++progname;
ops = 0;
while ((ch = getopt(argc, argv, "b:C:d:k:l:o:P:")) != EOF)
switch (ch) {
case 'b':
bulkbufsize = (u_int32_t)atoi(optarg);
break;
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'd':
datasize = (u_int)atoi(optarg);
break;
case 'k':
keysize = (u_int)atoi(optarg);
break;
case 'l':
logbufsize = (u_int32_t)atoi(optarg);
break;
case 'o':
ops = (u_int)atoi(optarg);
break;
case 'P':
pagesize = (u_int32_t)atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 1)
return (usage());
numitems = (cachesize / (keysize + datasize - 1)) / 2;
if (strcasecmp(argv[0], "read") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_ds(ops, 0);
printf(
"# %u in-memory Btree database reads of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "bulk") == 0) {
if (keysize < 8) {
fprintf(stderr,
"%s: bulk read requires a key size >= 10\n", progname);
return (EXIT_FAILURE);
}
/*
* The ops value is the number of bulk operations, not key get
* operations. Reduce the value so the test doesn't take so
* long, and use the returned number of retrievals as the ops
* value for timing purposes.
*/
if (ops == 0)
ops = 100000;
op_ds_bulk(ops, &total);
ops = total;
printf(
"# %u bulk in-memory Btree database reads of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "write") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_ds(ops, 1);
printf(
"# %u in-memory Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "txn-read") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_tds(ops, 0, 0, 0);
printf(
"# %u transactional in-memory Btree database reads of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "txn-write") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
#if defined(DB_LOG_INMEMORY) || defined(DB_LOG_IN_MEMORY)
#if defined(DB_LOG_INMEMORY)
op_tds(ops, 1, 0, DB_LOG_INMEMORY);
#else
op_tds(ops, 1, 0, DB_LOG_IN_MEMORY);
#endif
printf(
"# %u transactional in-memory logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
#else
return (EXIT_SUCCESS);
#endif
} else if (strcasecmp(argv[0], "txn-nosync") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
op_tds(ops, 1, DB_TXN_NOSYNC, 0);
printf(
"# %u transactional nosync logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else if (strcasecmp(argv[0], "txn-write-nosync") == 0) {
if (ops == 0)
ops = DEFAULT_OPS;
#ifdef DB_TXN_WRITE_NOSYNC
op_tds(ops, 1, DB_TXN_WRITE_NOSYNC, 0);
printf(
"# %u transactional OS-write/nosync logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
#else
return (EXIT_SUCCESS);
#endif
} else if (strcasecmp(argv[0], "txn-sync") == 0) {
/*
* Flushing to disk takes a long time, reduce the number of
* default ops.
*/
if (ops == 0)
ops = 100000;
op_tds(ops, 1, 0, 0);
printf(
"# %u transactional logging Btree database writes of %u/%u byte key/data pairs\n",
ops, keysize, datasize);
} else {
fprintf(stderr, "%s: unknown keyword %s\n", progname, argv[0]);
return (EXIT_FAILURE);
}
TIMER_DISPLAY(ops);
return (EXIT_SUCCESS);
}
static int
usage()
{
fprintf(stderr, "usage: %s %s%s%s%s",
progname, "[-b bulkbufsz] [-C cachesz]\n\t",
"[-d datasize] [-k keysize] [-l logbufsz] [-o ops] [-P pagesz]\n\t",
"[read | bulk | write | txn-read |\n\t",
"txn-write | txn-nosync | txn-write-nosync | txn-sync]\n");
return (EXIT_FAILURE);
}
#else
int
b_inmem(int argc, char *argv[])
{
COMPQUIET(argc, 0);
COMPQUIET(argv, NULL);
return (0);
}
#endif

160
test_micro/source/b_load.c Normal file
View File

@@ -0,0 +1,160 @@
/*
* $Id: b_load.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_load(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBTYPE type;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize;
int ch, i, count, duplicate;
char *ts, buf[32];
type = DB_BTREE;
cachesize = MEGABYTE;
count = 100000;
duplicate = 0;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:dt:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 'd':
duplicate = 1;
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Usage. */
if (duplicate && (type == DB_QUEUE || type == DB_RECNO)) {
fprintf(stderr,
"b_load: Queue an Recno don't support duplicates\n");
return (usage());
}
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
/*
* DB versions prior to 3.1.17 didn't have off-page duplicates, so
* this test can run forever.
*/
if (duplicate)
return (0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, NULL, 0) == 0);
DB_BENCH_ASSERT(dbp->set_cachesize(dbp, 0, cachesize, 0) == 0);
if (duplicate)
DB_BENCH_ASSERT(dbp->set_flags(dbp, DB_DUP) == 0);
dbp->set_errfile(dbp, stderr);
/* Set record length for Queue. */
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, 20) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* Insert count in-order key/data pairs. */
TIMER_START;
if (duplicate) {
key.size = 10;
key.data = "01234567890123456789";
data.data = buf;
data.size = 20;
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%020d", i);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
} else {
data.data = buf;
data.size = 20;
if (type == DB_BTREE || type == DB_HASH) {
key.size = 10;
key.data = buf;
for (i = 0; i < count; ++i) {
(void)snprintf(buf, sizeof(buf), "%010d", i);
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
} else {
key.data = &recno;
key.size = sizeof(recno);
for (i = 0, recno = 1; i < count; ++i, ++recno)
DB_BENCH_ASSERT(
dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
}
TIMER_STOP;
printf("# %d %s database in-order put of 10/20 byte key/data %sitems\n",
count, ts, duplicate ? "duplicate " : "");
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_load [-d] [-C cachesz] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

140
test_micro/source/b_open.c Normal file
View File

@@ -0,0 +1,140 @@
/*
* $Id: b_open.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_open(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DB *dbp;
DBTYPE type;
int ch, i, count;
char *fname, *dbname, *ts;
type = DB_BTREE;
count = 1000;
fname = dbname = NULL;
ts = "Btree";
while ((ch = getopt(argc, argv, "c:dft:")) != EOF)
switch (ch) {
case 'c':
count = atoi(optarg);
break;
case 'd':
dbname = "dbname";
break;
case 'f':
fname = "filename";
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
#if DB_VERSION_MAJOR < 4
/*
* Don't run in-memory database tests on versions less than 3, it
* takes forever and eats memory.
*/
if (fname == NULL && dbname == NULL)
return (0);
#endif
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 4
/*
* Named in-memory databases weren't available until 4.4.
*/
if (fname == NULL && dbname != NULL)
return (0);
#endif
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, fname, dbname, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, fname, dbname, type, DB_CREATE, 0666) == 0);
#endif
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
/* Open the database count times. */
TIMER_START;
for (i = 0; i < count; ++i) {
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, fname, dbname, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, fname, dbname, type, DB_CREATE, 0666) == 0);
#endif
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
}
TIMER_STOP;
printf("# %d %s %sdatabase open/close pairs\n",
count, ts,
fname == NULL ?
(dbname == NULL ? "in-memory " : "named in-memory ") :
(dbname == NULL ? "" : "sub-"));
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_open [-df] [-c count] [-t type]\n");
return (EXIT_FAILURE);
}

217
test_micro/source/b_put.c Normal file
View File

@@ -0,0 +1,217 @@
/*
* $Id: b_put.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
static int b_put_secondary(DB *, const DBT *, const DBT *, DBT *);
int
b_put(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DB *dbp, **second;
DBTYPE type;
DBT key, data;
db_recno_t recno;
u_int32_t cachesize;
int ch, dsize, i, count, secondaries;
char *ts, buf[64];
second = NULL;
type = DB_BTREE;
cachesize = MEGABYTE;
dsize = 20;
count = 100000;
secondaries = 0;
ts = "Btree";
while ((ch = getopt(argc, argv, "C:c:d:s:t:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case 'd':
dsize = atoi(optarg);
break;
case 's':
secondaries = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
ts = "Btree";
type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
ts = "Hash";
type = DB_HASH;
break;
case 'Q': case 'q':
if (b_util_have_queue())
return (0);
ts = "Queue";
type = DB_QUEUE;
break;
case 'R': case 'r':
ts = "Recno";
type = DB_RECNO;
break;
default:
return (usage());
}
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 3
/*
* Secondaries were added after DB 3.2.9.
*/
if (secondaries)
return (0);
#endif
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
DB_BENCH_ASSERT(dbenv->set_cachesize(dbenv, 0, cachesize, 0) == 0);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#endif
/*
* Create the database.
* Optionally set the record length for Queue.
*/
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
if (type == DB_QUEUE)
DB_BENCH_ASSERT(dbp->set_re_len(dbp, (u_int32_t)dsize) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(
dbp->open(dbp, NULL, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, type, DB_CREATE, 0666) == 0);
#endif
/* Optionally create the secondaries. */
if (secondaries != 0) {
DB_BENCH_ASSERT((second =
calloc(sizeof(DB *), (size_t)secondaries)) != NULL);
for (i = 0; i < secondaries; ++i) {
DB_BENCH_ASSERT(db_create(&second[i], dbenv, 0) == 0);
snprintf(buf, sizeof(buf), "%d.db", i);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(second[i]->open(second[i], NULL,
buf, NULL, DB_BTREE, DB_CREATE, 0600) == 0);
#else
DB_BENCH_ASSERT(second[i]->open(second[i],
buf, NULL, DB_BTREE, DB_CREATE, 0600) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR >= 3
#if DB_VERSION_MAJOR > 3 && DB_VERSION_MINOR > 0
/*
* The DB_TXN argument to Db.associate was added in
* 4.1.25.
*/
DB_BENCH_ASSERT(dbp->associate(
dbp, NULL, second[i], b_put_secondary, 0) == 0);
#else
DB_BENCH_ASSERT(dbp->associate(
dbp, second[i], b_put_secondary, 0) == 0);
#endif
#endif
}
}
/* Store a key/data pair. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
switch (type) {
case DB_BTREE:
case DB_HASH:
key.data = "01234567890123456789";
key.size = 20;
break;
case DB_QUEUE:
case DB_RECNO:
recno = 1;
key.data = &recno;
key.size = sizeof(recno);
break;
case DB_UNKNOWN:
b_util_abort();
break;
}
DB_BENCH_ASSERT(
(data.data = malloc(data.size = (size_t)dsize)) != NULL);
/* Store the key/data pair count times. */
TIMER_START;
for (i = 0; i < count; ++i)
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
TIMER_STOP;
if (type == DB_BTREE || type == DB_HASH)
printf(
"# %d %s database put of 10 byte key, %lu byte data",
count, ts, (u_long)dsize);
else
printf("# %d %s database put of key, %lu byte data",
count, ts, (u_long)dsize);
if (secondaries)
printf(" with %d secondaries", secondaries);
printf("\n");
TIMER_DISPLAY(count);
if (second != NULL) {
for (i = 0; i < secondaries; ++i)
DB_BENCH_ASSERT(second[i]->close(second[i], 0) == 0);
free(second);
}
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
b_put_secondary(dbp, pkey, pdata, skey)
DB *dbp;
const DBT *pkey, *pdata;
DBT *skey;
{
skey->data = pkey->data;
skey->size = pkey->size;
COMPQUIET(dbp, NULL);
COMPQUIET(pdata, NULL);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_put %s\n",
"[-C cachesz] [-c count] [-d bytes] [-s secondaries] [-t type]");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,137 @@
/*
* $Id: b_recover.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_recover(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBT key, data;
DB_ENV *dbenv;
DB_TXN *txn;
u_int32_t cachesize;
int ch, i, count;
/*
* Recover was too slow before release 4.0 that it's not worth
* running the test.
*/
#if DB_VERSION_MAJOR < 4
return (0);
#endif
cachesize = MEGABYTE;
count = 1000;
while ((ch = getopt(argc, argv, "C:c:")) != EOF)
switch (ch) {
case 'C':
cachesize = (u_int32_t)atoi(optarg);
break;
case 'c':
count = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
DB_BENCH_ASSERT(dbenv->set_cachesize(dbenv, 0, cachesize, 0) == 0);
#define OFLAGS \
(DB_CREATE | DB_INIT_LOCK | \
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE)
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, NULL, OFLAGS, 0666) == 0);
#endif
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, OFLAGS, 0666) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, OFLAGS, 0666) == 0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(dbp, NULL,
TESTFILE, NULL, DB_BTREE, DB_CREATE | DB_AUTO_COMMIT, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.size = data.size = 20;
key.data = data.data = "01234567890123456789";
/* Start/commit a transaction count times. */
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(
txn_begin(dbenv, NULL, &txn, DB_TXN_NOSYNC) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn_commit(txn, 0) == 0);
#else
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, DB_TXN_NOSYNC) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
#endif
}
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
/* Create a new DB_ENV handle. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
DB_BENCH_ASSERT(
dbenv->set_cachesize(dbenv, 0, 1048576 /* 1MB */, 0) == 0);
/* Now run recovery. */
TIMER_START;
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(dbenv->open(
dbenv, TESTDIR, NULL, OFLAGS | DB_RECOVER, 0666) == 0);
#endif
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, OFLAGS | DB_RECOVER, 0666) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 1
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, OFLAGS | DB_RECOVER, 0666) == 0);
#endif
TIMER_STOP;
/*
* We divide the time by the number of transactions, so an "operation"
* is the recovery of a single transaction.
*/
printf("# recovery after %d transactions\n", count);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_recover [-C cachesz] [-c count]\n");
return (EXIT_FAILURE);
}

89
test_micro/source/b_txn.c Normal file
View File

@@ -0,0 +1,89 @@
/*
* $Id: b_txn.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage(void);
int
b_txn(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DB_TXN *txn;
int tabort, ch, i, count;
count = 1000;
tabort = 0;
while ((ch = getopt(argc, argv, "ac:")) != EOF)
switch (ch) {
case 'a':
tabort = 1;
break;
case 'c':
count = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
NULL, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR,
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE, 0666) == 0);
#endif
/* Start and commit/abort a transaction count times. */
TIMER_START;
if (tabort)
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn_abort(txn) == 0);
#else
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn->abort(txn) == 0);
#endif
}
else
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn_commit(txn, 0) == 0);
#else
DB_BENCH_ASSERT(
dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
#endif
}
TIMER_STOP;
printf("# %d empty transaction start/%s pairs\n",
count, tabort ? "abort" : "commit");
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_txn [-a] [-c count]\n");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,168 @@
/*
* $Id: b_txn_write.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int usage __P((void));
#ifdef DB_INIT_REP
static int b_txn_write_send __P((DB_ENV *,
const DBT *, const DBT *, const DB_LSN *, int, u_int32_t));
/*
* b_txn_write_send --
* A stubbed-out replication message function.
*/
static int
b_txn_write_send(dbenv, control, rec, lsn, eid, flags)
DB_ENV *dbenv;
const DBT *control, *rec;
const DB_LSN *lsn;
int eid;
u_int32_t flags;
{
COMPQUIET(dbenv, NULL);
COMPQUIET(control, NULL);
COMPQUIET(rec, NULL);
COMPQUIET(lsn, NULL);
COMPQUIET(eid, 0);
COMPQUIET(flags, 0);
return (0);
}
#endif
int
b_txn_write(int argc, char *argv[])
{
extern char *optarg;
extern int optind;
DB *dbp;
DBT key, data;
DB_ENV *dbenv;
DB_TXN *txn;
u_int32_t flags, oflags;
int ch, i, count, rep_stub;
char *config;
count = 1000;
oflags = flags = 0;
rep_stub = 0;
config = "synchronous";
while ((ch = getopt(argc, argv, "ac:rw")) != EOF)
switch (ch) {
case 'a':
config = "nosync";
flags = DB_TXN_NOSYNC;
break;
case 'c':
count = atoi(optarg);
break;
case 'r':
#ifdef DB_INIT_REP
rep_stub = 1;
#else
exit(0);
#endif
break;
case 'w':
config = "write-nosync";
#ifdef DB_TXN_WRITE_NOSYNC
flags = DB_TXN_WRITE_NOSYNC;
#else
exit(0);
#endif
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
#ifdef DB_INIT_REP
if (rep_stub) {
#if DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 5 || DB_VERSION_MAJOR > 4
DB_BENCH_ASSERT(
dbenv->rep_set_transport(dbenv, 1, b_txn_write_send) == 0);
#else
DB_BENCH_ASSERT(
dbenv->set_rep_transport(dbenv, 1, b_txn_write_send) == 0);
#endif
oflags |= DB_INIT_REP;
}
#endif
oflags |= DB_CREATE | DB_INIT_LOCK |
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN | DB_PRIVATE;
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 0
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, NULL, flags | oflags, 0666) == 0);
#endif
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR == 1
DB_BENCH_ASSERT(
dbenv->open(dbenv, TESTDIR, flags | oflags, 0666) == 0);
#endif
#if DB_VERSION_MAJOR > 3 || DB_VERSION_MINOR > 1
if (flags != 0)
DB_BENCH_ASSERT(dbenv->set_flags(dbenv, flags, 1) == 0);
DB_BENCH_ASSERT(dbenv->open(dbenv, TESTDIR, oflags, 0666) == 0);
#endif
#ifdef DB_INIT_REP
if (rep_stub)
DB_BENCH_ASSERT(
dbenv->rep_start(dbenv, NULL, DB_REP_MASTER) == 0);
#endif
/* Create the database. */
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(dbp, NULL,
TESTFILE, NULL, DB_BTREE, DB_CREATE | DB_AUTO_COMMIT, 0666) == 0);
#else
DB_BENCH_ASSERT(
dbp->open(dbp, TESTFILE, NULL, DB_BTREE, DB_CREATE, 0666) == 0);
#endif
/* Initialize the data. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.size = data.size = 20;
key.data = data.data = "01234567890123456789";
/* Start/commit a transaction count times. */
TIMER_START;
for (i = 0; i < count; ++i) {
#if DB_VERSION_MAJOR < 4
DB_BENCH_ASSERT(txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn_commit(txn, 0) == 0);
#else
DB_BENCH_ASSERT(dbenv->txn_begin(dbenv, NULL, &txn, 0) == 0);
DB_BENCH_ASSERT(dbp->put(dbp, txn, &key, &data, 0) == 0);
DB_BENCH_ASSERT(txn->commit(txn, 0) == 0);
#endif
}
TIMER_STOP;
printf("# %d %stransactions write %s commit pairs\n",
count, rep_stub ? "replicated ": "", config);
TIMER_DISPLAY(count);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
return (0);
}
static int
usage()
{
(void)fprintf(stderr, "usage: b_txn_write [-arw] [-c count]\n");
return (EXIT_FAILURE);
}

143
test_micro/source/b_uname.c Normal file
View File

@@ -0,0 +1,143 @@
/*
* $Id: b_uname.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
#define UNAMEFILE "NODENAME"
static int write_info __P((FILE *));
int
b_uname()
{
FILE *fp;
int ret;
if ((fp = fopen(UNAMEFILE, "w")) == NULL)
goto file_err;
ret = write_info(fp);
if (fclose(fp) != 0) {
file_err: fprintf(stderr,
"%s: %s: %s\n", progname, UNAMEFILE, strerror(errno));
return (1);
}
return (ret);
}
#ifdef DB_WIN32
static int
write_info(fp)
FILE *fp;
{
OSVERSIONINFO osver;
SYSTEM_INFO sysinfo;
char *p;
#ifdef DB_WINCE
p = "WinCE";
#else
{
DWORD len;
char buf[1024];
len = sizeof(buf) - 1;
GetComputerName(buf, &len);
p = buf;
}
#endif
fprintf(fp, "<p>%s, ", p);
GetSystemInfo(&sysinfo);
switch (sysinfo.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_ALPHA:
p = "alpha";
break;
case PROCESSOR_ARCHITECTURE_INTEL:
p = "x86";
break;
case PROCESSOR_ARCHITECTURE_MIPS:
p = "mips";
break;
case PROCESSOR_ARCHITECTURE_PPC:
p = "ppc";
break;
default:
p = "unknown";
break;
}
fprintf(fp, "%s<br>\n", p);
memset(&osver, 0, sizeof(osver));
osver.dwOSVersionInfoSize = sizeof(osver);
GetVersionEx(&osver);
switch (osver.dwPlatformId) {
case VER_PLATFORM_WIN32_NT: /* NT, Windows 2000 or Windows XP */
if (osver.dwMajorVersion == 4)
p = "Windows NT4x";
else if (osver.dwMajorVersion <= 3)
p = "Windows NT3x";
else if (osver.dwMajorVersion == 5 && osver.dwMinorVersion < 1)
p = "Windows 2000";
else if (osver.dwMajorVersion >= 5)
p = "Windows XP";
else
p = "unknown";
break;
case VER_PLATFORM_WIN32_WINDOWS: /* Win95, Win98 or WinME */
if ((osver.dwMajorVersion > 4) ||
((osver.dwMajorVersion == 4) && (osver.dwMinorVersion > 0))) {
if (osver.dwMinorVersion >= 90)
p = "Windows ME";
else
p = "Windows 98";
} else
p = "Windows 95";
break;
case VER_PLATFORM_WIN32s: /* Windows 3.x */
p = "Windows";
break;
default:
p = "unknown";
break;
}
fprintf(fp,
"%s, %ld.%02ld", p, osver.dwMajorVersion, osver.dwMinorVersion);
return (0);
}
#elif defined(HAVE_VXWORKS)
static int
write_info(fp)
FILE *fp;
{
fprintf(fp, "<p>VxWorks");
return (0);
}
#else /* POSIX */
#include <sys/utsname.h>
static int
write_info(fp)
FILE *fp;
{
struct utsname name;
if (uname(&name) == 0)
fprintf(fp, "<p>%s, %s<br>\n%s, %s, %s</p>\n", name.nodename,
name.machine, name.sysname, name.release, name.version);
else {
/*
* We've seen random failures on some systems, complain and
* skip the call if it fails.
*/
fprintf(stderr, "%s: uname: %s\n", progname, strerror(errno));
fprintf(fp, "<p>POSIX");
}
return (0);
}
#endif

154
test_micro/source/b_util.c Normal file
View File

@@ -0,0 +1,154 @@
/*
* $Id: b_util.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
static int testdir_remove __P((char *));
int
b_util_have_hash()
{
#if defined(HAVE_HASH) ||\
DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 2
return (0);
#else
fprintf(stderr,
"library build did not include support for the Hash access method\n");
return (1);
#endif
}
int
b_util_have_queue()
{
#if defined(HAVE_QUEUE) ||\
DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 2
return (0);
#else
fprintf(stderr,
"library build did not include support for the Queue access method\n");
return (1);
#endif
}
/*
* b_util_dir_setup --
* Create the test directory.
*/
int
b_util_dir_setup()
{
int ret;
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 3
if ((ret = __os_mkdir(NULL, TESTDIR, 0755)) != 0) {
#else
if ((ret = mkdir(TESTDIR, 0755)) != 0) {
#endif
fprintf(stderr,
"%s: %s: %s\n", progname, TESTDIR, db_strerror(ret));
return (1);
}
return (0);
}
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 4
#define OS_EXISTS(a, b, c) __os_exists(a, b, c)
#else
#define OS_EXISTS(a, b, c) __os_exists(b, c)
#endif
/*
* b_util_dir_teardown
* Clean up the test directory.
*/
int
b_util_dir_teardown()
{
int ret;
if (OS_EXISTS(NULL, TESTFILE, NULL) == 0 &&
(ret = b_util_unlink(TESTFILE)) != 0) {
fprintf(stderr,
"%s: %s: %s\n", progname, TESTFILE, db_strerror(ret));
return (1);
}
return (testdir_remove(TESTDIR) ? 1 : 0);
}
/*
* testdir_remove --
* Remove a directory and all its contents, the "dir" must contain no
* subdirectories, because testdir_remove will not recursively delete
* all subdirectories.
*/
static int
testdir_remove(dir)
char *dir;
{
int cnt, i, isdir, ret;
char buf[1024], **names;
ret = 0;
/* If the directory doesn't exist, we're done. */
if (OS_EXISTS(NULL, dir, &isdir) != 0)
return (0);
/* Get a list of the directory contents. */
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 6
if ((ret = __os_dirlist(NULL, dir, 0, &names, &cnt)) != 0)
return (ret);
#else
if ((ret = __os_dirlist(NULL, dir, &names, &cnt)) != 0)
return (ret);
#endif
/* Go through the file name list, remove each file in the list */
for (i = 0; i < cnt; ++i) {
(void)snprintf(buf, sizeof(buf),
"%s%c%s", dir, PATH_SEPARATOR[0], names[i]);
if ((ret = OS_EXISTS(NULL, buf, &isdir)) != 0)
goto file_err;
if (!isdir && (ret = b_util_unlink(buf)) != 0) {
file_err: fprintf(stderr, "%s: %s: %s\n",
progname, buf, db_strerror(ret));
break;
}
}
__os_dirfree(NULL, names, cnt);
/*
* If we removed the contents of the directory, remove the directory
* itself.
*/
if (i == cnt && (ret = rmdir(dir)) != 0)
fprintf(stderr,
"%s: %s: %s\n", progname, dir, db_strerror(errno));
return (ret);
}
void
b_util_abort()
{
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 6
abort();
#elif DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR == 6
__os_abort();
#else
__os_abort(NULL);
#endif
}
int
b_util_unlink(path)
char *path;
{
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 7
return (__os_unlink(NULL, path));
#else
return (__os_unlink(NULL, path, 0));
#endif
}

View File

@@ -0,0 +1,623 @@
/*
* $Id: b_workload.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
#include "b_workload.h"
static int dump_verbose_stats __P((DB *, CONFIG *));
static int is_del_workload __P((int));
static int is_get_workload __P((int));
static int is_put_workload __P((int));
static int run_mixed_workload __P((DB *, CONFIG *));
static int run_std_workload __P((DB *, CONFIG *));
static int usage __P((void));
static char *workload_str __P((int));
/*
* General TODO list:
* * The workload type. Might work better as a bitmask than the current enum.
* * Improve the verbose stats, so they can be easily parsed.
* * Think about doing automatic btree/hash comparison in here.
*/
int
b_workload(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
CONFIG conf;
DB *dbp;
DB_ENV *dbenv;
int ch, ffactor, ksz;
dbenv = NULL;
memset(&conf, 0, sizeof(conf));
conf.seed = 124087;
srand(conf.seed);
conf.pcount = 100000;
conf.ts = "Btree";
conf.type = DB_BTREE;
conf.dsize = 20;
conf.presize = 0;
conf.workload = T_PUT_GET_DELETE;
while ((ch = getopt(argc, argv, "b:c:d:e:g:ik:m:op:r:t:vw:")) != EOF)
switch (ch) {
case 'b':
conf.cachesz = atoi(optarg);
break;
case 'c':
conf.pcount = atoi(optarg);
break;
case 'd':
conf.dsize = atoi(optarg);
break;
case 'e':
conf.cursor_del = atoi(optarg);
break;
case 'g':
conf.gcount = atoi(optarg);
break;
case 'i':
conf.presize = 1;
break;
case 'k':
conf.ksize = atoi(optarg);
break;
case 'm':
conf.message = optarg;
break;
case 'o':
conf.orderedkeys = 1;
break;
case 'p':
conf.pagesz = atoi(optarg);
break;
case 'r':
conf.num_dups = atoi(optarg);
break;
case 't':
switch (optarg[0]) {
case 'B': case 'b':
conf.ts = "Btree";
conf.type = DB_BTREE;
break;
case 'H': case 'h':
if (b_util_have_hash())
return (0);
conf.ts = "Hash";
conf.type = DB_HASH;
break;
default:
return (usage());
}
break;
case 'v':
conf.verbose = 1;
break;
case 'w':
switch (optarg[0]) {
case 'A':
conf.workload = T_PUT_GET_DELETE;
break;
case 'B':
conf.workload = T_GET;
break;
case 'C':
conf.workload = T_PUT;
break;
case 'D':
conf.workload = T_DELETE;
break;
case 'E':
conf.workload = T_PUT_GET;
break;
case 'F':
conf.workload = T_PUT_DELETE;
break;
case 'G':
conf.workload = T_GET_DELETE;
break;
case 'H':
conf.workload = T_MIXED;
break;
default:
return (usage());
}
break;
case '?':
default:
fprintf(stderr, "Invalid option: %c\n", ch);
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/*
* Validate the input parameters if specified.
*/
if (conf.pagesz != 0)
DB_BENCH_ASSERT(conf.pagesz >= 512 && conf.pagesz <= 65536 &&
((conf.pagesz & (conf.pagesz - 1)) == 0));
if (conf.cachesz != 0)
DB_BENCH_ASSERT(conf.cachesz > 20480);
DB_BENCH_ASSERT(conf.ksize == 0 || conf.orderedkeys == 0);
/* Create the environment. */
DB_BENCH_ASSERT(db_env_create(&dbenv, 0) == 0);
dbenv->set_errfile(dbenv, stderr);
if (conf.cachesz != 0)
DB_BENCH_ASSERT(
dbenv->set_cachesize(dbenv, 0, conf.cachesz, 0) == 0);
#if DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 1
DB_BENCH_ASSERT(dbenv->open(dbenv, "TESTDIR",
NULL, DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbenv->open(dbenv, "TESTDIR",
DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE, 0666) == 0);
#endif
DB_BENCH_ASSERT(db_create(&dbp, dbenv, 0) == 0);
if (conf.pagesz != 0)
DB_BENCH_ASSERT(
dbp->set_pagesize(dbp, conf.pagesz) == 0);
if (conf.presize != 0 && conf.type == DB_HASH) {
ksz = (conf.orderedkeys != 0) ? sizeof(u_int32_t) : conf.ksize;
if (ksz == 0)
ksz = 10;
ffactor = (conf.pagesz - 32)/(ksz + conf.dsize + 8);
fprintf(stderr, "ffactor: %d\n", ffactor);
DB_BENCH_ASSERT(
dbp->set_h_ffactor(dbp, ffactor) == 0);
DB_BENCH_ASSERT(
dbp->set_h_nelem(dbp, conf.pcount*10) == 0);
}
#if DB_VERSION_MAJOR >= 4 && DB_VERSION_MINOR >= 1
DB_BENCH_ASSERT(dbp->open(
dbp, NULL, TESTFILE, NULL, conf.type, DB_CREATE, 0666) == 0);
#else
DB_BENCH_ASSERT(dbp->open(
dbp, TESTFILE, NULL, conf.type, DB_CREATE, 0666) == 0);
#endif
if (conf.workload == T_MIXED)
run_mixed_workload(dbp, &conf);
else
run_std_workload(dbp, &conf);
if (is_put_workload(conf.workload) == 0)
timespecadd(&conf.tot_time, &conf.put_time);
if (is_get_workload(conf.workload) == 0)
timespecadd(&conf.tot_time, &conf.get_time);
if (is_del_workload(conf.workload) == 0)
timespecadd(&conf.tot_time, &conf.del_time);
/* Ensure data is flushed for following measurements. */
DB_BENCH_ASSERT(dbp->sync(dbp, 0) == 0);
if (conf.verbose != 0)
dump_verbose_stats(dbp, &conf);
DB_BENCH_ASSERT(dbp->close(dbp, 0) == 0);
DB_BENCH_ASSERT(dbenv->close(dbenv, 0) == 0);
/*
* Construct a string for benchmark output.
*
* Insert HTML in-line to make the output prettier -- ugly, but easy.
*/
printf("# workload test: %s: %s<br>%lu ops",
conf.ts, workload_str(conf.workload), (u_long)conf.pcount);
if (conf.ksize != 0)
printf(", key size: %lu", (u_long)conf.ksize);
if (conf.dsize != 0)
printf(", data size: %lu", (u_long)conf.dsize);
if (conf.pagesz != 0)
printf(", page size: %lu", (u_long)conf.pagesz);
else
printf(", page size: default");
if (conf.cachesz != 0)
printf(", cache size: %lu", (u_long)conf.cachesz);
else
printf(", cache size: default");
printf(", %s keys", conf.orderedkeys == 1 ? "ordered" : "unordered");
printf(", num dups: %lu", (u_long)conf.num_dups);
printf("\n");
if (conf.workload != T_MIXED) {
if (conf.message != NULL)
printf("%s %s ", conf.message, conf.ts);
TIME_DISPLAY(conf.pcount, conf.tot_time);
} else
TIMER_DISPLAY(conf.pcount);
return (0);
}
/*
* The mixed workload is designed to simulate a somewhat real
* usage scenario.
* NOTES: * rand is used to decide on the current operation. This will
* be repeatable, since the same seed is always used.
* * All added keys are stored in a FIFO queue, this is not very
* space efficient, but is the best way I could come up with to
* insert random key values, and be able to retrieve/delete them.
* * TODO: the workload will currently only work with unordered
* fixed length keys.
*/
#define GET_PROPORTION 90
#define PUT_PROPORTION 7
#define DEL_PROPORTION 3
static int
run_mixed_workload(dbp, config)
DB *dbp;
CONFIG *config;
{
DBT key, data;
size_t next_op, i, ioff;
char kbuf[KBUF_LEN];
struct bench_q operation_queue;
/* Having ordered insertion does not make sense here */
DB_BENCH_ASSERT(config->orderedkeys == 0);
srand(config->seed);
memset(&operation_queue, 0, sizeof(struct bench_q));
ioff = 0;
INIT_KEY(key, config);
memset(&data, 0, sizeof(data));
DB_BENCH_ASSERT(
(data.data = malloc(data.size = config->dsize)) != NULL);
/*
* Add an initial sample set of data to the DB.
* This should add some stability, and reduce the likelihood
* of deleting all of the entries in the DB.
*/
for (i = 0; i < 2 * config->pcount; ++i) {
GET_KEY_NEXT(key, config, kbuf, i);
BENCH_Q_TAIL_INSERT(operation_queue, kbuf);
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
TIMER_START;
for (i = 0; i < config->pcount; ++i) {
next_op = rand()%100;
if (next_op < GET_PROPORTION ) {
BENCH_Q_POP_PUSH(operation_queue, kbuf);
key.data = kbuf;
key.size = sizeof(kbuf);
dbp->get(dbp, NULL, &key, &data, 0);
} else if (next_op < GET_PROPORTION+PUT_PROPORTION) {
GET_KEY_NEXT(key, config, kbuf, i);
BENCH_Q_TAIL_INSERT(operation_queue, kbuf);
dbp->put(dbp, NULL, &key, &data, 0);
} else {
BENCH_Q_POP(operation_queue, kbuf);
key.data = kbuf;
key.size = sizeof(kbuf);
dbp->del(dbp, NULL, &key, 0);
}
}
TIMER_STOP;
TIMER_GET(config->tot_time);
return (0);
}
static int
run_std_workload(dbp, config)
DB *dbp;
CONFIG *config;
{
DBT key, data;
DBC *dbc;
u_int32_t i;
int ret;
char kbuf[KBUF_LEN];
/* Setup a key/data pair. */
INIT_KEY(key, config);
memset(&data, 0, sizeof(data));
DB_BENCH_ASSERT(
(data.data = malloc(data.size = config->dsize)) != NULL);
/* Store the key/data pair count times. */
TIMER_START;
for (i = 0; i < config->pcount; ++i) {
GET_KEY_NEXT(key, config, kbuf, i);
DB_BENCH_ASSERT(dbp->put(dbp, NULL, &key, &data, 0) == 0);
}
TIMER_STOP;
TIMER_GET(config->put_time);
if (is_get_workload(config->workload) == 0) {
TIMER_START;
for (i = 0; i <= config->gcount; ++i) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while ((dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0);
DB_BENCH_ASSERT(dbc->c_close(dbc) == 0);
}
TIMER_STOP;
TIMER_GET(config->get_time);
}
if (is_del_workload(config->workload) == 0) {
/* reset rand to reproduce key sequence. */
srand(config->seed);
TIMER_START;
if (config->cursor_del != 0) {
DB_BENCH_ASSERT(dbp->cursor(dbp, NULL, &dbc, 0) == 0);
while (
(ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) == 0)
DB_BENCH_ASSERT(dbc->c_del(dbc, 0) == 0);
DB_BENCH_ASSERT (ret == DB_NOTFOUND);
} else {
INIT_KEY(key, config);
for (i = 0; i < config->pcount; ++i) {
GET_KEY_NEXT(key, config, kbuf, i);
ret = dbp->del(dbp, NULL, &key, 0);
/*
* Random key generation can cause dups,
* so NOTFOUND result is OK.
*/
if (config->ksize == 0)
DB_BENCH_ASSERT
(ret == 0 || ret == DB_NOTFOUND);
else
DB_BENCH_ASSERT(ret == 0);
}
}
TIMER_STOP;
TIMER_GET(config->del_time);
}
return (0);
}
static int
dump_verbose_stats(dbp, config)
DB *dbp;
CONFIG *config;
{
/*
* It would be nice to be able to define stat as _stat on
* Windows, but that substitutes _stat for the db call as well.
*/
#ifdef DB_WIN32
struct _stat fstat;
#else
struct stat fstat;
#endif
DB_HASH_STAT *hstat;
DB_BTREE_STAT *bstat;
double free_prop;
char path[1024];
#ifdef DB_BENCH_INCLUDE_CONFIG_SUMMARY
printf("Completed workload benchmark.\n");
printf("Configuration summary:\n");
printf("\tworkload type: %d\n", (int)config->workload);
printf("\tdatabase type: %s\n", config->ts);
if (config->cachesz != 0)
printf("\tcache size: %lu\n", (u_long)config->cachesz);
if (config->pagesz != 0)
printf("\tdatabase page size: %lu\n", (u_long)config->pagesz);
printf("\tput element count: %lu\n", (u_long)config->pcount);
if ( is_get_workload(config->workload) == 0)
printf("\tget element count: %lu\n", (u_long)config->gcount);
if (config->orderedkeys)
printf("\tInserting items in order\n");
else if (config->ksize == 0)
printf("\tInserting keys with size 10\n");
else
printf(
"\tInserting keys with size: %lu\n", (u_long)config->ksize);
printf("\tInserting data elements size: %lu\n", (u_long)config->dsize);
if (is_del_workload(config->workload) == 0) {
if (config->cursor_del)
printf("\tDeleting items using a cursor\n");
else
printf("\tDeleting items without a cursor\n");
}
#endif /* DB_BENCH_INCLUDE_CONFIG_SUMMARY */
if (is_put_workload(config->workload) == 0)
printf("%s Time spent inserting (%lu) (%s) items: %lu/%lu\n",
config->message[0] == '\0' ? "" : config->message,
(u_long)config->pcount, config->ts,
(u_long)config->put_time.tv_sec, config->put_time.tv_nsec);
if (is_get_workload(config->workload) == 0)
printf("%s Time spent getting (%lu) (%s) items: %lu/%lu\n",
config->message[0] == '\0' ? "" : config->message,
(u_long)config->pcount * ((config->gcount == 0) ?
1 : config->gcount), config->ts,
(u_long)config->get_time.tv_sec, config->get_time.tv_nsec);
if (is_del_workload(config->workload) == 0)
printf("%s Time spent deleting (%lu) (%s) items: %lu/%lu\n",
config->message[0] == '\0' ? "" : config->message,
(u_long)config->pcount, config->ts,
(u_long)config->del_time.tv_sec, config->del_time.tv_nsec);
(void)snprintf(path, sizeof(path),
"%s%c%s", TESTDIR, PATH_SEPARATOR[0], TESTFILE);
#ifdef DB_WIN32
if (_stat(path, &fstat) == 0) {
#else
if (stat(path, &fstat) == 0) {
#endif
printf("%s Size of db file (%s): %lu K\n",
config->message[0] == '\0' ? "" : config->message,
config->ts, (u_long)fstat.st_size/1024);
}
if (config->type == DB_HASH) {
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &hstat, NULL, 0) == 0);
#elif DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &hstat, 0) == 0);
#else
DB_BENCH_ASSERT(dbp->stat(dbp, NULL, &hstat, 0) == 0);
#endif
/*
* Hash fill factor is a bit tricky. Want to include
* both bucket and overflow buckets (not offpage).
*/
free_prop = hstat->hash_pagesize*hstat->hash_buckets;
free_prop += hstat->hash_pagesize*hstat->hash_overflows;
free_prop =
(free_prop - hstat->hash_bfree - hstat->hash_ovfl_free)/
free_prop;
printf("%s db fill factor (%s): %.2f%%\n",
config->message[0] == '\0' ? "" : config->message,
config->ts, free_prop*100);
free(hstat);
} else { /* Btree */
#if DB_VERSION_MAJOR < 3 || DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &bstat, NULL, 0) == 0);
#elif DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR <= 2
DB_BENCH_ASSERT(dbp->stat(dbp, &bstat, 0) == 0);
#else
DB_BENCH_ASSERT(dbp->stat(dbp, NULL, &bstat, 0) == 0);
#endif
free_prop = bstat->bt_pagesize*bstat->bt_leaf_pg;
free_prop = (free_prop-bstat->bt_leaf_pgfree)/free_prop;
printf("%s db fill factor (%s): %.2f%%\n",
config->message[0] == '\0' ? "" : config->message,
config->ts, free_prop*100);
free(bstat);
}
return (0);
}
static char *
workload_str(workload)
int workload;
{
static char buf[128];
switch (workload) {
case T_PUT_GET_DELETE:
return ("PUT/GET/DELETE");
/* NOTREACHED */
case T_GET:
return ("GET");
/* NOTREACHED */
case T_PUT:
return ("PUT");
/* NOTREACHED */
case T_DELETE:
return ("DELETE");
/* NOTREACHED */
case T_PUT_GET:
return ("PUT/GET");
/* NOTREACHED */
case T_PUT_DELETE:
return ("PUT/DELETE");
/* NOTREACHED */
case T_GET_DELETE:
return ("GET/DELETE");
/* NOTREACHED */
case T_MIXED:
snprintf(buf, sizeof(buf), "MIXED (get: %d, put: %d, del: %d)",
(int)GET_PROPORTION,
(int)PUT_PROPORTION, (int)DEL_PROPORTION);
return (buf);
default:
break;
}
exit(usage());
/* NOTREACHED */
}
static int
is_get_workload(workload)
int workload;
{
switch (workload) {
case T_GET:
case T_PUT_GET:
case T_PUT_GET_DELETE:
case T_GET_DELETE:
return 0;
}
return 1;
}
static int
is_put_workload(workload)
int workload;
{
switch (workload) {
case T_PUT:
case T_PUT_GET:
case T_PUT_GET_DELETE:
case T_PUT_DELETE:
return 0;
}
return 1;
}
static int
is_del_workload(workload)
int workload;
{
switch (workload) {
case T_DELETE:
case T_PUT_DELETE:
case T_PUT_GET_DELETE:
case T_GET_DELETE:
return 0;
}
return 1;
}
static int
usage()
{
(void)fprintf(stderr,
"usage: b_workload [-b cachesz] [-c count] [-d bytes] [-e]\n");
(void)fprintf(stderr,
"\t[-g getitrs] [-i] [-k keysize] [-m message] [-o] [-p pagesz]\n");
(void)fprintf(stderr, "\t[-r dup_count] [-t type] [-w type]\n");
(void)fprintf(stderr, "Where:\n");
(void)fprintf(stderr, "\t-b the size of the DB cache.\n");
(void)fprintf(stderr, "\t-c the number of elements to be measured.\n");
(void)fprintf(stderr, "\t-d the size of each data element.\n");
(void)fprintf(stderr, "\t-e delete entries using a cursor.\n");
(void)fprintf(stderr, "\t-g number of get cursor traverses.\n");
(void)fprintf(stderr, "\t-i Pre-init hash DB bucket count.\n");
(void)fprintf(stderr, "\t-k the size of each key inserted.\n");
(void)fprintf(stderr, "\t-m message pre-pended to log output.\n");
(void)fprintf(stderr, "\t-o keys should be ordered for insert.\n");
(void)fprintf(stderr, "\t-p the page size for the database.\n");
(void)fprintf(stderr, "\t-r the number of duplicates to insert\n");
(void)fprintf(stderr, "\t-t type of the underlying database.\n");
(void)fprintf(stderr, "\t-w the workload to measure, available:\n");
(void)fprintf(stderr, "\t\tA - PUT_GET_DELETE\n");
(void)fprintf(stderr, "\t\tB - GET\n");
(void)fprintf(stderr, "\t\tC - PUT\n");
(void)fprintf(stderr, "\t\tD - DELETE\n");
(void)fprintf(stderr, "\t\tE - PUT_GET\n");
(void)fprintf(stderr, "\t\tF - PUT_DELETE\n");
(void)fprintf(stderr, "\t\tG - GET_DELETE\n");
(void)fprintf(stderr, "\t\tH - MIXED\n");
return (EXIT_FAILURE);
}

View File

@@ -0,0 +1,149 @@
/*
* $Id: b_workload.h 63573 2008-05-23 21:43:21Z trent.nelson $
*/
/*
* Macros to help with initializing/assigning key dbts
*/
#define KBUF_LEN 12
#define INIT_KEY(key, config) do { \
memset(&key, 0, sizeof(key)); \
if (config->orderedkeys) { \
key.size = sizeof (u_int32_t); \
} else if (config->ksize != 0) { \
DB_BENCH_ASSERT( \
(key.data = malloc(key.size = config->ksize)) != NULL); \
} else { \
key.data = kbuf; \
key.size = 10; \
} \
} while (0)
#define GET_KEY_NEXT(key, config, kbuf, i) do { \
size_t tmp_int; \
if (config->orderedkeys) { \
/* Will be sorted on little-endian system. */ \
tmp_int = i; \
M_32_SWAP(tmp_int); \
key.data = &tmp_int; \
} else if (config->ksize == 0) { \
/* \
* This will produce duplicate keys. \
* That is not such a big deal, since we are \
* using the same seed to srand each time, \
* the scenario is reproducible. \
*/ \
(void)snprintf(kbuf, sizeof(kbuf), "%10d", rand()); \
} else { \
/* TODO: Not sure of the best approach here. */ \
(void)snprintf(key.data, config->ksize, "%10lu", (u_long)i); \
} \
} while (0)
/* Taken from dbinc/db_swap.h */
#undef M_32_SWAP
#define M_32_SWAP(a) { \
u_int32_t _tmp; \
_tmp = (u_int32_t)a; \
((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[3]; \
((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[2]; \
((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[1]; \
((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[0]; \
}
/*
* A singly linked list, that maintains a pointer
* to the start and the end of the queue.
* Should be possible to use a STAILQ, but this seemed easier
*/
typedef struct bench_qentry {
char data[KBUF_LEN];
struct bench_qentry *next;
}bench_qentry;
typedef struct bench_q {
struct bench_qentry *head;
struct bench_qentry *tail;
} bench_q;
#define BENCH_Q_TAIL_INSERT(queue, buf) do { \
struct bench_qentry *entry; \
DB_BENCH_ASSERT( \
(entry = malloc(sizeof(struct bench_qentry))) != NULL); \
memcpy(entry->data, buf, sizeof(entry->data)); \
if (queue.head == NULL) \
queue.head = queue.tail = entry; \
else { \
queue.tail->next = entry; \
queue.tail = entry; \
} \
} while (0)
#define BENCH_Q_POP(queue, buf) do { \
struct bench_qentry *popped = queue.head; \
if (popped == NULL) \
break; \
if (queue.head->next == NULL) \
queue.head = queue.tail = NULL; \
else \
queue.head = queue.head->next; \
memcpy(buf, popped->data, sizeof(buf)); \
free(popped); \
} while (0)
/*
* Retrieve the head of the queue, save the data into user
* buffer, and push the item back onto the end of the list.
* Same functionality as pop/insert, but saves a malloc/free
*/
#define BENCH_Q_POP_PUSH(queue, buf) do { \
struct bench_qentry *popped = queue.head; \
if (popped == NULL) \
break; \
if (queue.head->next == NULL) \
queue.head = queue.tail = NULL; \
else \
queue.head = queue.head->next; \
memcpy(buf, popped->data, sizeof(buf)); \
if (queue.head == NULL) \
queue.head = queue.tail = popped; \
else { \
queue.tail->next = popped; \
queue.tail = popped; \
} \
} while (0)
typedef enum {
T_PUT,
T_GET,
T_DELETE,
T_PUT_GET,
T_PUT_DELETE,
T_PUT_GET_DELETE,
T_GET_DELETE,
T_MIXED
} test_type;
typedef struct
{
size_t ksize;
size_t dsize;
size_t orderedkeys;
size_t num_dups;
size_t pagesz;
size_t cachesz;
size_t pcount;
size_t gcount;
size_t cursor_del;
size_t verbose;
test_type workload;
size_t seed;
size_t presize;
DBTYPE type;
char *ts;
char *message;
/* Fields used to store timing information */
db_timespec put_time;
db_timespec get_time;
db_timespec del_time;
db_timespec tot_time;
} CONFIG;

211
test_micro/source/bench.h Normal file
View File

@@ -0,0 +1,211 @@
/*
* $Id: bench.h 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#ifndef _BENCH_H_
#define _BENCH_H_
#include "db_config.h"
#include "db_int.h"
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 5
/*
* Older releases of Berkeley DB don't include standard include files in
* db_int.h.
*/
#ifdef DB_WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#include <direct.h>
#include <sys/timeb.h>
#else
#include <sys/stat.h>
#include <sys/time.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#endif
#endif
#define TESTDIR "TESTDIR"
#define TESTFILE "test_micro.db"
/*
* Implement a custom assert to allow consistent behavior across builds and
* platforms.
*
* The BDB library DB_ASSERT implementation is only enabled in diagnostic
* builds -- so is not suitable here.
*/
#define DB_BENCH_ASSERT(e) do { \
(e) ? (void)0 : \
(fprintf(stderr, \
"assert failure: %s/%d: \"%s\"\n", __FILE__, __LINE__, #e), \
b_util_abort()); \
} while (0)
#ifndef NS_PER_SEC
#define NS_PER_SEC 1000000000 /* Nanoseconds in a second */
#endif
#ifndef NS_PER_US
#define NS_PER_US 1000 /* Nanoseconds in a microsecond */
#endif
#ifndef MS_PER_NS
#define MS_PER_NS 1000000 /* Milliseconds in a nanosecond */
#endif
#ifdef DB_TIMEOUT_TO_TIMESPEC
/*
* We have the timer routines in the Berkeley DB library after their conversion
* to the POSIX timespec interfaces. We'd rather use something that gives us
* better information than elapsed wallclock time, so use getrusage instead if
* it's available.
*/
#ifdef HAVE_GETRUSAGE
#include <sys/resource.h>
#define SET_TIMER_FROM_GETRUSAGE(tp) do { \
struct rusage __usage; \
DB_BENCH_ASSERT(getrusage(RUSAGE_SELF, &__usage) == 0); \
(tp)->tv_sec = \
__usage.ru_utime.tv_sec + __usage.ru_stime.tv_sec; \
(tp)->tv_nsec = NS_PER_US * \
(__usage.ru_utime.tv_usec + __usage.ru_stime.tv_usec); \
} while (0);
#define TIMER_START SET_TIMER_FROM_GETRUSAGE(&__start_time);
#define TIMER_STOP SET_TIMER_FROM_GETRUSAGE(&__end_time);
#elif defined(DB_WIN32) && !defined(DB_WINCE)
#define SET_TIMER_FROM_GETPROCESSTIMES(tp) do { \
FILETIME lpCreationTime, lpExitTime, lpKernelTime, lpUserTIme; \
LARGE_INTEGER large_int; \
LONGLONG __ns_since_epoch; \
DB_BENCH_ASSERT( \
GetProcessTimes(GetCurrentProcess(), &lpCreationTime, \
&lpExitTime, &lpKernelTime, &lpUserTIme) != 0); \
memcpy(&large_int, &lpKernelTime, sizeof(lpKernelTime)); \
__ns_since_epoch = (large_int.QuadPart * 100); \
(tp)->tv_sec = (time_t)(__ns_since_epoch / NS_PER_SEC); \
(tp)->tv_nsec = (long)(__ns_since_epoch % NS_PER_SEC); \
memcpy(&large_int, &lpUserTIme, sizeof(lpUserTIme)); \
__ns_since_epoch = (large_int.QuadPart * 100); \
(tp)->tv_sec += (time_t)(__ns_since_epoch / NS_PER_SEC); \
(tp)->tv_nsec += (long)(__ns_since_epoch % NS_PER_SEC); \
} while (0);
#define TIMER_START SET_TIMER_FROM_GETPROCESSTIMES(&__start_time);
#define TIMER_STOP SET_TIMER_FROM_GETPROCESSTIMES(&__end_time);
#else /* !HAVEGETRUSAGE && !DB_WIN32 */
#if DB_VERSION_MAJOR > 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 6
#define TIMER_START __os_gettime(NULL, &__start_time, 1)
#define TIMER_STOP __os_gettime(NULL, &__end_time, 1)
#else
#define TIMER_START __os_gettime(NULL, &__start_time)
#define TIMER_STOP __os_gettime(NULL, &__end_time)
#endif
#endif /* !HAVE_GETRUSAGE */
#else /* !DB_TIMEOUT_TO_TIMESPEC */
#if defined(HAVE_CLOCK_GETTIME)
typedef struct timespec db_timespec;
#else
typedef struct {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
} db_timespec;
#endif
#define timespecadd(vvp, uvp) \
do { \
(vvp)->tv_sec += (uvp)->tv_sec; \
(vvp)->tv_nsec += (uvp)->tv_nsec; \
if ((vvp)->tv_nsec >= NS_PER_SEC) { \
(vvp)->tv_sec++; \
(vvp)->tv_nsec -= NS_PER_SEC; \
} \
} while (0)
#define timespecsub(vvp, uvp) \
do { \
(vvp)->tv_sec -= (uvp)->tv_sec; \
(vvp)->tv_nsec -= (uvp)->tv_nsec; \
if ((vvp)->tv_nsec < 0) { \
(vvp)->tv_sec--; \
(vvp)->tv_nsec += NS_PER_SEC; \
} \
} while (0)
#define TIMER_START CLOCK(__start_time)
#define TIMER_STOP CLOCK(__end_time)
#if defined(HAVE_CLOCK_GETTIME)
#define CLOCK(tm) do { \
DB_BENCH_ASSERT(clock_gettime( \
CLOCK_REALTIME, (struct timespec *)&(tm)) == 0); \
} while (0)
#elif defined(DB_WIN32)
#define CLOCK(tm) do { \
struct _timeb __now; \
_ftime(&__now); \
(tm).tv_sec = __now.time; \
(tm).tv_nsec = __now.millitm * MS_PER_NS; \
} while (0)
#else
#define CLOCK(tm) do { \
struct timeval __tp; \
DB_BENCH_ASSERT(gettimeofday(&__tp, NULL) == 0); \
(tm).tv_sec = __tp.tv_sec; \
(tm).tv_nsec = __tp.tv_usec * NS_PER_US; \
} while (0)
#endif
#endif /* !DB_TIMEOUT_TO_TIMESPEC */
db_timespec __start_time, __end_time;
#define TIMER_GET(tm) do { \
tm = __end_time; \
timespecsub(&(tm), &__start_time); \
} while (0)
#define TIMER_DISPLAY(ops) do { \
db_timespec __tmp_time; \
__tmp_time = __end_time; \
timespecsub(&__tmp_time, &__start_time); \
TIME_DISPLAY(ops, __tmp_time); \
} while (0)
#define TIME_DISPLAY(ops, tm) do { \
double __secs; \
int __major, __minor, __patch; \
__secs = (tm).tv_sec + (double)(tm).tv_nsec / NS_PER_SEC; \
(void)db_version(&__major, &__minor, &__patch); \
printf("%d.%d.%d\t%.2f\n", __major, __minor, __patch, \
(__secs == 0) ? 0.0 : (ops) / __secs); \
} while (0)
extern char *progname; /* program name */
int b_curalloc __P((int, char *[]));
int b_curwalk __P((int, char *[]));
int b_del __P((int, char *[]));
int b_get __P((int, char *[]));
int b_inmem __P((int, char *[]));
int b_load __P((int, char *[]));
int b_open __P((int, char *[]));
int b_put __P((int, char *[]));
int b_recover __P((int, char *[]));
int b_txn __P((int, char *[]));
int b_txn_write __P((int, char *[]));
int b_uname __P((void));
void b_util_abort __P((void));
int b_util_dir_setup __P((void));
int b_util_dir_teardown __P((void));
int b_util_have_hash __P((void));
int b_util_have_queue __P((void));
int b_util_unlink __P((char *));
int b_workload __P((int, char *[]));
#endif /* !_BENCH_H_ */

View File

@@ -0,0 +1,217 @@
/*
* $Id: test_micro.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "bench.h"
int main __P((int, char *[]));
static int run __P((char *));
static int usage __P((void));
char *progname; /* program name */
static int test_start = 1; /* first test to run */
static int test_end = 0; /* last test to run */
static struct {
char *name; /* command name */
int (*f)(int, char *[]); /* function */
} cmdlist[] = {
{ "b_curalloc", b_curalloc },
{ "b_curwalk", b_curwalk },
{ "b_del", b_del },
{ "b_get", b_get },
{ "b_inmem", b_inmem },
{ "b_load", b_load },
{ "b_open", b_open },
{ "b_put", b_put },
{ "b_recover", b_recover },
{ "b_txn", b_txn },
{ "b_txn_write", b_txn_write },
{ "b_workload", b_workload },
{ NULL, NULL }
};
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
int ch, ret;
char *run_directory, *ifile;
if ((progname = __db_rpath(argv[0])) == NULL)
progname = argv[0];
else
++progname;
#ifdef DB_BREW
if (bdb_brew_begin() != 0) {
fprintf(stderr,
"%s: failed to initialize Berkeley DB on BREW\n");
return (EXIT_FAILURE);
}
#endif
run_directory = NULL;
ifile = "run.std";
while ((ch = getopt(argc, argv, "d:e:i:s:")) != EOF)
switch (ch) {
case 'd':
run_directory = optarg;
break;
case 'e':
test_end = atoi(optarg);
break;
case 'i':
ifile = optarg;
break;
case 's':
test_start = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
/* Run in the target directory. */
if (run_directory != NULL && chdir(run_directory) != 0) {
fprintf(stderr,
"%s: %s: %s\n", progname, run_directory, strerror(errno));
return (1);
}
/* Clean up any left-over test directory. */
if (b_util_dir_teardown())
return (1);
ret = run(ifile);
#ifdef DB_BREW
bdb_brew_end();
#endif
return (ret ? EXIT_FAILURE : EXIT_SUCCESS);
}
/*
* run --
* Read a configuration file and run the tests.
*/
static int
run(ifile)
char *ifile;
{
#ifdef HAVE_GETOPT_OPTRESET
extern int optreset;
#endif
extern int optind;
static int test_cur = 0;
FILE *ifp;
int argc, cmdindx, lineno, ret;
char *p, cmd[1024], path[1024], **argv;
/* Identify the run. */
if (b_uname() != 0)
return (1);
/* Open the list of tests. */
if ((ifp = fopen(ifile, "r")) == NULL) {
fprintf(stderr,
"%s: %s: %s\n", progname, ifile, strerror(errno));
return (1);
}
for (lineno = 1; fgets(cmd, sizeof(cmd), ifp) != NULL; ++lineno) {
/*
* Nul-terminate the command line; check for a trailing \r
* on Windows.
*/
if ((p = strchr(cmd, '\n')) == NULL) {
format_err: fprintf(stderr, "%s: %s: line %d: illegal input\n",
progname, ifile, lineno);
return (1);
}
if (p > cmd && p[-1] == '\r')
--p;
*p = '\0';
/* Skip empty lines and comments. */
if (cmd[0] == '\0' || cmd[0] == '#')
continue;
/* Optionally limit the test run to specific tests. */
if (++test_cur < test_start ||
(test_end != 0 && test_cur > test_end))
continue;
fprintf(stderr, "%d: %s\n", test_cur, cmd);
/* Find the command. */
if ((p = strchr(cmd, ' ')) == NULL)
goto format_err;
*p++ = '\0';
for (cmdindx = 0; cmdlist[cmdindx].name != NULL; ++cmdindx)
if (strcmp(cmd, cmdlist[cmdindx].name) == 0)
break;
if (cmdlist[cmdindx].name == NULL)
goto format_err;
/* Build argc/argv. */
if (__db_util_arg(cmd, p, &argc, &argv) != 0)
return (1);
/* Re-direct output into the test log file. */
(void)snprintf(path, sizeof(path), "%d", test_cur);
if (freopen(path, "a", stdout) == NULL) {
fprintf(stderr,
"%s: %s: %s\n", progname, path, strerror(errno));
return (1);
}
/*
* Each underlying "program" re-parses its arguments --
* reset getopt.
*/
#ifdef HAVE_GETOPT_OPTRESET
optreset = 1;
#endif
optind = 1;
/* Prepare the test directory. */
if (b_util_dir_setup())
return (1);
ret = cmdlist[cmdindx].f(argc, argv);
/* Clean up the test directory. */
if (b_util_dir_teardown())
return (1);
(void)fflush(stdout);
#if DB_VERSION_MAJOR < 4 || DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR < 1
__os_free(NULL, argv, 0);
#else
__os_free(NULL, argv);
#endif
if (ret != 0)
return (ret);
}
return (0);
}
static int
usage()
{
(void)fprintf(stderr,
"usage: %s [-d directory] [-e end] [-i input] [-s start]\n",
progname);
return (EXIT_FAILURE);
}

135
test_micro/test_micro Normal file
View File

@@ -0,0 +1,135 @@
#! /bin/sh
#
# $Id: test_micro,v 1.51 2008/04/14 02:21:47 david Exp $
# build_test_micro_posix
# Build test_micro on a POSIX system.
build_test_micro_posix()
{
# See if there's a test_micro binary already.
test $clean -eq 0 && test -x test_micro && return 0
echo 'Compiling test_micro...'
rm -f test_micro
CC=${CC:-gcc}
if [ "$CC" = "gcc" ]; then
CC="$CC -O3 -Wall"
else
CC="$CC -O"
fi
$CC -I. -I.. -I../include -I../include_auto -I$h/source\
$SRC -o test_micro libdb.a $LIBS || return 1
}
# build_test_micro_windows
# Build test_micro on a Windows system.
build_test_micro_windows()
{
# See if there's a test_micro binary already.
test $clean -eq 0 && test -x test_micro && return 0
echo 'Compiling test_micro...'
rm -f test_micro
cl /nologo /o test_micro /DDB_WIN32 /G6 /Ox /MD\
-I.. -I../.. -I../include -I../include_auto $SRC $WINSRC\
libdb*.lib ws2_32.lib advapi32.lib || return 1
}
# run --
# $1: args
run()
{
# You can set the MAJOR and MINOR environment variables to limit
# the BDB releases on which the tests are run.
for i in db-${MAJOR:-[3-9]}.${MINOR:-*}.*; do
if [ -f $i/build_unix/libdb.a ] ; then
(cd $i/build_unix/ &&
build_test_micro_posix || exit 1)
elif [ -f $i/build_win*/Release/libdb??.lib ] ; then
(cd $i/build_win*/Release &&
build_test_micro_windows || exit 1)
fi
echo "$i run begins: `date`"
echo "test_micro $1..."
if [ -f $i/build_unix/libdb.a ] ; then
(cd $i/build_unix/ && ./test_micro $1 || exit 1)
elif [ -f $i/build_win*/Release/libdb??.lib ] ; then
(cd $i/build_win*/Release && ./test_micro $1 || exit 1)
fi
echo "$i run ends: `date`"
done
}
# Get a path to this shellscript.
t=`dirname $0`
h=`(cd $t && echo $PWD)`
# We may need to re-compile, create a list of our sources.
SRC="$h/source/b_curalloc.c $h/source/b_curwalk.c $h/source/b_del.c
$h/source/b_get.c $h/source/b_inmem.c $h/source/b_load.c
$h/source/b_open.c $h/source/b_put.c $h/source/b_recover.c
$h/source/b_txn.c $h/source/b_txn_write.c $h/source/b_uname.c
$h/source/b_util.c $h/source/b_workload.c $h/source/test_micro.c
$h/../common/util_arg.c"
WINSRC="$h/../clib/getopt.c"
# Process arguments.
clean=0 # Rebuild test_micro
workload=0 # Run workload tests
start_test=0 # Start test
end_test=0 # End test
while :
do case "$1" in
-c) # Rebuild test_micro.
clean=1
shift;;
-w) # Run workload tests
workload=1
shift;;
[1-9]*-[0-9]*) # Range: -3, 3-, 3-10
start_test=`echo $1|sed 's/-.*//'`
start_test=${start_test:=1}
end_test=`echo $1|sed 's/.*-//'`
end_test=${end_test:=0}
shift;;
[1-9]*) # Specific test
start_test="$1"
end_test="$1"
shift;;
*)
break;;
esac
done
test "$#" -ne 0 && {
echo 'usage: test_micro [-cw] [# | #- | -# | #-#]' >& 2
exit 1
}
if test $start_test != 0; then
cmd="$cmd -s $start_test"
fi
if test $end_test != 0; then
cmd="$cmd -e $end_test"
fi
# Create the run directory, and initialize test_micro's arguments.
t=RUN.`hostname | sed 's/\..*//'`
[ -d $t ] || mkdir $t
cmd="$cmd -d `(cd $t && pwd)`"
# Set input file.
if test "$workload" -eq 1; then
cmd="$cmd -i $h/configs/run.workload"
else
cmd="$cmd -i $h/configs/run.std"
fi
# Flush any I/O, just to get as a clean a timing as we can, ignore errors,
# sync is privleged on some systems.
(sync && sleep 1 2>&1) > /dev/null
run "$cmd"
exit 0