1# Some example and timing tests of the new hash/blocked/ordered views
2
3if [catch {package require Mk4tcl}] {
4  catch {load ./Mk4tcl.so mk4tcl}
5  catch {load ./Mk4tcl_d.dll mk4tcl}
6}
7
8proc timedRun {tag count args} {
9  set usec [lindex [time $args $count] 0]
10  if {$usec >= 1000000} {
11    set t [format {%.2f seconds} [expr {$usec/1000000.0}]]
12  } elseif {$usec >= 1000} {
13    set t [format {%.2f mSec} [expr {$usec/1000.0}]]
14  } else {
15    set t [format {%d uS} $usec]
16  }
17  puts [format {     %-10s %5dx -> %s} $tag $count $t]
18  return $usec
19}
20
21proc setupPlain {} {
22  global blocked_data
23
24  file delete _large.mk
25  mk::file open db _large.mk -nocommit
26
27  if $blocked_data {
28    mk::view layout db.words {{_B {k1 k2:I v:I}}}
29    mk::view open db.words rawdata
30    catch {rename words ""}
31    rename [rawdata view blocked] words
32  } else {
33    mk::view layout db.words {k1 k2:I v:I}
34    mk::view open db.words words
35  }
36}
37
38proc teardownPlain {} {
39  teardown
40}
41
42proc setupHash {} {
43  global blocked_data blocked_map
44
45  file delete _large.mk
46  mk::file open db _large.mk -nocommit
47
48  if $blocked_data {
49    mk::view layout db.words {{_B {k1 k2:I v:I}}}
50    mk::view open db.words rawdata
51    catch {rename data ""}
52    rename [rawdata view blocked] data
53  } else {
54    mk::view layout db.words {k1 k2:I v:I}
55    mk::view open db.words data
56  }
57
58  if $blocked_map {
59    mk::view layout db.words_map {{_B {_H:I _R:I}}}
60    mk::view open db.words_map rawmap
61    #catch {rename map ""}
62    #rename [rawmap view blocked] map
63    set map [rawmap view blocked]
64  } else {
65    mk::view layout db.words_map {_H:I _R:I}
66    mk::view open db.words_map map
67    set map map
68  }
69
70  #rename [data view hash map 2] words
71  rename [data view hash $map 2] words
72}
73
74proc teardownHash {} {
75  teardown
76}
77
78proc setupOrdered {} {
79  global blocked_data
80
81  file delete _large.mk
82  mk::file open db _large.mk -nocommit
83
84  if $blocked_data {
85    mk::view layout db.words {{_B {k1 k2:I v:I}}}
86    mk::view open db.words rawdata
87    catch {rename data ""}
88    rename [rawdata view blocked] data
89  } else {
90    mk::view layout db.words {k1 k2:I v:I}
91    mk::view open db.words data
92  }
93
94  rename [data view ordered 2] words
95}
96
97proc teardownOrdered {} {
98  teardown
99}
100
101proc setupBoth {} {
102  global blocked_data blocked_map
103
104  file delete _large.mk
105  mk::file open db _large.mk -nocommit
106
107  if $blocked_data {
108    mk::view layout db.words {{_B {k1 k2:I v:I}}}
109    mk::view open db.words rawdata
110    catch {rename data ""}
111    rename [rawdata view blocked] data
112  } else {
113    mk::view layout db.words {k1 k2:I v:I}
114    mk::view open db.words data
115  }
116
117  if $blocked_map {
118    mk::view layout db.words_map {{_B {_H:I _R:I}}}
119    mk::view open db.words_map rawmap
120    #catch {rename map ""}
121    #rename [rawmap view blocked] map
122    set map [rawmap view blocked]
123  } else {
124    mk::view layout db.words_map {_H:I _R:I}
125    mk::view open db.words_map map
126    set map map
127  }
128
129  #catch {rename hash ""}
130  #rename [data view hash map 2] hash
131  set hash [data view hash $map 2]
132
133  #rename [hash view ordered 2] words
134  rename [$hash view ordered 2] words
135}
136
137proc teardownBoth {} {
138  teardown
139}
140
141proc teardown {} {
142  rename words ""
143  rename hash ""
144  rename data ""
145  rename map ""
146
147  rename rawdata ""
148  rename rawmap ""
149
150  mk::file close db
151}
152
153proc filldb {n} {
154  puts -nonewline stderr " filldb $n ... "
155  set fd [open words]
156
157  set n0 [words size]
158  set t0 [clock clicks]
159  while {[gets $fd w] >= 0} {
160    words insert end k1 $w k2 $n v [expr {$n * [string length $w]}]
161    #if {[words size] % 1000 == 0} {puts -nonewline stderr *}
162  }
163  set usec [expr {[clock clicks]-$t0}]
164
165  close $fd
166  set rps [expr {int(([words size]-$n0) / ($usec / 1000000.0))}]
167  puts stderr "$rps adds/sec ($n0..[words size] rows)"
168}
169
170proc run {type bdata bmap runs finds} {
171  global blocked_data blocked_map
172  set blocked_data $bdata
173  set blocked_map $bmap
174
175  set s ""
176  if $bdata {append s " - data is blocked"}
177  if $bmap {append s " - map is blocked"}
178
179  puts "\n*** $type$s ***\n"
180
181  proc map {args} {return ?}
182  proc rawmap {args} {return ?}
183  proc data {args} {return ?}
184  proc rawdata {args} {return ?}
185  proc hash {args} {return ?}
186
187  setup$type
188
189  set runCounter 99
190
191  while {[incr runs -1] >= 0} {
192    timedRun Fill 1 filldb [incr runCounter]
193    timedRun Commit 1 mk::file commit db
194    timedRun Find $finds words find k1 iterator k2 $runCounter
195  }
196
197  puts " [words size] rows, [map size] hash slots,\
198      file size = [file size _large.mk]"
199  puts "     [rawdata size] data blocks, [rawmap size] map blocks"
200
201  teardown$type
202}
203
204  # plain table, append at end, find with linear scan
205run Plain 0 0 3 10
206run Plain 1 0 3 10
207
208  # hash table, with data and/or map optionally blocked
209run Hash 0 0 3 1000
210run Hash 0 1 3 1000
211run Hash 1 0 3 1000
212run Hash 1 1 3 1000
213
214  # binary search, with data optionally blocked
215run Ordered 0 0 3 1000
216run Ordered 1 0 3 1000
217
218  # combination of the above: hash access, rows kept in sort order
219run Both 0 0 2 1000
220run Both 0 1 2 1000
221run Both 1 0 2 1000
222run Both 1 1 2 1000
223
224  # create larger datasets, this takes a long time
225run Plain 1 0 10 10
226run Hash  1 0 10 1000
227run Ordered 1 0 10 1000
228run Both  1 0 10 1000
229