AryaWu/sqlite
0
1#!/bin/sh2# the next line restarts using tclsh \3exec tclsh "$0" ${1+"$@"}4#5# This program runs performance testing on sqlite3.c. Usage:6set usage {USAGE:7 8 speedtest.tcl sqlite3.c x1.txt trunk.txt -Os -DSQLITE_ENABLE_STAT49 | | | `-----------------------'10 File to test ----' | | |11 | | `- options12 Output filename --------' |13 `--- optional prior output to diff14 15Do a cache-grind performance analysis of the sqlite3.c file named and16write the results into the output file. The ".txt" is appended to the17output file (and diff-file) name if it is not already present. If the18diff-file is specified then show a diff from the diff-file to the new19output.20 21Other options include:22 CC=... Specify an alternative C compiler. Default is "gcc".23 -D... -D and -O options are passed through to the C compiler.24 --dryrun Show what would happen but don't do anything.25 --help Show this help screen.26 --lean "Lean" mode.27 --lookaside N SZ Lookahead uses N slots of SZ bytes each.28 --osmalloc Use the OS native malloc() instead of MEMSYS529 --pagesize N Use N as the page size.30 --quiet | -q "Quite". Put results in file but don't pop up editor31 --size N Change the test size. 100 means 100%. Default: 5.32 --testset TEST Specify the specific testset to use. The default33 is "mix1". Other options include: "main", "json",34 "cte", "orm", "fp", "rtree".35}36set srcfile {}37set outfile {}38set difffile {}39set cflags {-DSQLITE_OMIT_LOAD_EXTENSION -DSQLITE_THREADSAFE=0}40set cc gcc41set testset mix142set dryrun 043set quiet 044set osmalloc 045set speedtestflags {--shrink-memory --reprepare --stats}46lappend speedtestflags --journal wal --size 547 48for {set i 0} {$i<[llength $argv]} {incr i} {49 set arg [lindex $argv $i]50 if {[string index $arg 0]=="-"} {51 switch -- $arg {52 -pagesize -53 --pagesize {54 lappend speedtestflags --pagesize55 incr i56 lappend speedtestflags [lindex $argv $i]57 }58 -lookaside -59 --lookaside {60 lappend speedtestflags --lookaside61 incr i62 lappend speedtestflags [lindex $argv $i]63 incr i64 lappend speedtestflags [lindex $argv $i]65 }66 -lean -67 --lean {68 lappend cflags \69 -DSQLITE_DEFAULT_MEMSTATUS=0 \70 -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1 \71 -DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 \72 -DSQLITE_MAX_EXPR_DEPTH=1 \73 -DSQLITE_OMIT_DECLTYPE \74 -DSQLITE_OMIT_DEPRECATED \75 -DSQLITE_OMIT_PROGRESS_CALLBACK \76 -DSQLITE_OMIT_SHARED_CACHE \77 -DSQLITE_USE_ALLOCA78 }79 -testset -80 --testset {81 incr i82 set testset [lindex $argv $i]83 }84 -size -85 --size {86 incr i87 set newsize [lindex $argv $i]88 if {$newsize<1} {set newsize 1}89 set speedtestflags \90 [regsub {.-size \d+} $speedtestflags "-size $newsize"]91 }92 -n -93 -dryrun -94 --dryrun {95 set dryrun 196 }97 -osmalloc -98 --osmalloc {99 set osmalloc 1100 }101 -? -102 -help -103 --help {104 puts $usage105 exit 0106 }107 -q -108 -quiet -109 --quiet {110 set quiet 1111 }112 default {113 lappend cflags $arg114 }115 }116 continue117 }118 if {[string match CC=* $arg]} {119 set cc [string range $arg 3 end]120 continue121 }122 if {[string match *.c $arg]} {123 if {$srcfile!=""} {124 puts stderr "multiple source files: $srcfile $arg"125 exit 1126 }127 set srcfile $arg128 continue129 }130 if {[lsearch {main cte rtree orm fp json parsenumber mix1} $arg]>=0} {131 set testset $arg132 continue133 }134 if {$outfile==""} {135 set outfile $arg136 continue137 }138 if {$difffile==""} {139 set difffile $arg140 continue141 }142 puts stderr "unknown option: \"$arg\". Use --help for more info."143 exit 1144}145if {[lsearch -glob $cflags -O*]<0} {146 lappend cflags -Os147}148if {!$osmalloc} {149 append speedtestflags { --heap 40000000 64}150}151if {!$osmalloc && [lsearch -glob $cflags {-DSQLITE_ENABLE_MEMSYS*}]<0} {152 lappend cflags -DSQLITE_ENABLE_MEMSYS5153}154if {[lsearch -glob $cflags {-DSQLITE_ENABLE_RTREE*}]<0} {155 lappend cflags -DSQLITE_ENABLE_RTREE156}157if {$srcfile==""} {158 puts stderr "no sqlite3.c source file specified"159 exit 1160}161if {![file readable $srcfile]} {162 puts stderr "source file \"$srcfile\" does not exist"163 exit 1164}165if {$outfile==""} {166 puts stderr "no output file specified"167 exit 1168}169if {![string match *.* [file tail $outfile]]} {170 append outfile .txt171}172if {$difffile!=""} {173 if {![file exists $difffile]} {174 if {[file exists $difffile.txt]} {175 append difffile .txt176 } else {177 puts stderr "No such file: \"$difffile\""178 exit 1179 }180 }181}182 183set cccmd [list $cc -g]184lappend cccmd -I[file dir $srcfile]185lappend cccmd {*}[lsort $cflags]186lappend cccmd [file dir $argv0]/speedtest1.c187lappend cccmd $srcfile188lappend cccmd -o speedtest1189puts $cccmd190if {!$dryrun} {191 exec {*}$cccmd192}193lappend speedtestflags --testset $testset194set stcmd [list valgrind --tool=cachegrind ./speedtest1 {*}$speedtestflags]195lappend stcmd speedtest1.db196lappend stcmd >valgrind-out.txt 2>valgrind-err.txt197puts $stcmd198if {!$dryrun} {199 foreach file {speedtest1.db speedtest1.db-journal speedtest1.db-wal200 speedtest1.db-shm} {201 if {[file exists $file]} {file delete $file}202 }203 exec {*}$stcmd204}205 206set maxmtime 0207set cgfile {}208foreach cgout [glob -nocomplain cachegrind.out.*] {209 if {[file mtime $cgout]>$maxmtime} {210 set cgfile $cgout211 set maxmtime [file mtime $cgfile]212 }213}214if {$cgfile==""} {215 puts "no cachegrind output"216 exit 1217}218 219############# Process the cachegrind.out.# file ##########################220set fd [open $outfile wb]221set in [open "|cg_annotate --show=Ir --auto=yes --context=40 $cgfile" r]222set dest !223set out(!) {}224set linenum 0225set cntlines 0 ;# true to remember cycle counts on each line226set seenSqlite3 0 ;# true if we have seen the sqlite3.c file227while {![eof $in]} {228 set line [string map {\t { }} [gets $in]]229 if {[regexp {^-- Auto-annotated source: (.*)} $line all name]} {230 set dest $name231 if {[string match */sqlite3.c $dest]} {232 set cntlines 1233 set seenSqlite3 1234 } else {235 set cntlines 0236 }237 } elseif {[regexp {^-- line (\d+) ------} $line all ln]} {238 set line [lreplace $line 2 2 {#}]239 set linenum [expr {$ln-1}]240 } elseif {[regexp {^The following files chosen for } $line]} {241 set dest !242 }243 append out($dest) $line\n244 if {$cntlines} {245 incr linenum246 if {[regexp {^ *([0-9,]+) } $line all x]} {247 set x [string map {, {}} $x]248 set cycles($linenum) $x249 }250 }251}252foreach x [lsort [array names out]] {253 puts $fd $out($x)254}255# If the sqlite3.c file has been seen, then output a summary of the256# cycle counts for each file that went into making up sqlite3.c257#258if {$seenSqlite3} {259 close $in260 set in [open sqlite3.c]261 set linenum 0262 set fn sqlite3.c263 set pattern1 {^/\*+ Begin file ([^ ]+) \*}264 set pattern2 {^/\*+ Continuing where we left off in ([^ ]+) \*}265 while {![eof $in]} {266 set line [gets $in]267 incr linenum268 if {[regexp $pattern1 $line all newfn]} {269 set fn $newfn270 } elseif {[regexp $pattern2 $line all newfn]} {271 set fn $newfn272 } elseif {[info exists cycles($linenum)]} {273 incr fcycles($fn) $cycles($linenum)274 }275 }276 close $in277 puts $fd \278 {**********************************************************************}279 set lx {}280 set sum 0281 foreach {fn cnt} [array get fcycles] {282 lappend lx [list $cnt $fn]283 incr sum $cnt284 }285 puts $fd [format {%20s %14d %8.3f%%} TOTAL $sum 100]286 foreach entry [lsort -index 0 -integer -decreasing $lx] {287 foreach {cnt fn} $entry break288 puts $fd [format {%20s %14d %8.3f%%} $fn $cnt [expr {$cnt*100.0/$sum}]]289 }290}291puts $fd "Executable size:"292close $fd293exec size speedtest1 >>$outfile294#295# Processed cachegrind output should now be in the $outfile296#############################################################################297 298if {$quiet} {299 # Skip this last part of popping up a GUI viewer300} elseif {$difffile!=""} {301 set fossilcmd {fossil xdiff --tk -c 20}302 lappend fossilcmd $difffile303 lappend fossilcmd $outfile304 lappend fossilcmd &305 puts $fossilcmd306 if {!$dryrun} {307 exec {*}$fossilcmd308 }309} else {310 if {!$dryrun} {311 exec open $outfile312 }313}314 