Skip to content

Commit 37fc1ea

Browse files
committed
Add delete benchmarking techniques
1 parent 552b482 commit 37fc1ea

File tree

2 files changed

+82
-36
lines changed

2 files changed

+82
-36
lines changed

src/tree/bench.clj

+82-36
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
[b backend]
2020
{:structure (core/b-tree (core/->Config b b 0))
2121
:insert core/insert
22+
:delete core/delete
2223
:flush (fn [x] (core/flush-tree x backend))})
2324

2425
(defn msg-b-tree
@@ -27,13 +28,15 @@
2728
(let [sqrt-b (long (Math/sqrt b))]
2829
{:structure (core/b-tree(core/->Config sqrt-b b (- b sqrt-b)))
2930
:insert msg/insert
31+
:delete msg/delete
3032
:flush (fn [x] (core/flush-tree x backend))}))
3133

3234
(defn sorted-set-repr
3335
"Returns a sorted set"
3436
[]
3537
{:structure (sorted-set)
3638
:insert conj
39+
:delete disj
3740
:flush (fn [set]
3841
{:tree set
3942
:stats (atom {})})})
@@ -58,20 +61,24 @@
5861
flush-freq is the number of keys per flush
5962
datastruct is the test data structure
6063
out is the stream to write the results to (as well as stdout)"
61-
[n dataset flush-freq datastruct out]
62-
(let [{:keys [structure insert flush]} datastruct]
63-
(loop [[x & data] (take n (:data dataset))
64+
[n dataset flush-freq datastruct out delete-xform]
65+
(let [{:keys [structure delete insert flush]} datastruct
66+
dataset (take n (:data dataset))]
67+
(loop [[x & data] dataset
6468
t 0
6569
tree structure
6670
last-flush nil
6771
i 0
72+
inserting? true
6873
outputs []]
6974
(let [i' (inc i)
7075
{flushed-tree :tree
7176
stats :stats} (when (zero? (mod i' flush-freq))
7277
(flush tree))
7378
before (System/nanoTime)
74-
tree' (insert (or flushed-tree tree) x)
79+
tree' (if inserting?
80+
(insert (or flushed-tree tree) x)
81+
(delete (or flushed-tree tree) x))
7582
after (System/nanoTime)
7683
log-inserts (zero? (mod i' (quot n 100)))
7784
updated-outputs (atom outputs)]
@@ -80,35 +87,53 @@
8087
(let [ks (sort (keys last-flush))
8188
avg-ns (float (/ t (quot n 100)))]
8289
(when (zero? i)
83-
(println (str "elements,insert_took_avg_ns,"
90+
(println (str "elements,op,insert_took_avg_ns,"
8491
(str/join "," ks))))
85-
(println (str i' "," avg-ns
92+
(println (str i' "," (if inserting? "insert" "delete") "," avg-ns
8693
"," (str/join "," (map #(get last-flush %) ks))))
8794
(swap! updated-outputs conj (-> (into {} last-flush)
88-
(assoc :avg-ns avg-ns
89-
:n i))))))
90-
(if (seq data)
95+
(assoc :ins-avg-ns avg-ns
96+
(if inserting?
97+
:insert
98+
:delete) true
99+
:n i'))))))
100+
(cond
101+
(seq data)
91102
(recur data
92103
(if log-inserts
93104
0
94105
(+ t (- after before)))
95106
tree'
96107
(if stats (merge-with + last-flush @stats) last-flush)
97108
i'
109+
inserting?
98110
@updated-outputs)
111+
inserting?
112+
(recur (delete-xform dataset)
113+
0
114+
tree'
115+
nil
116+
i'
117+
false
118+
@updated-outputs)
119+
:else
99120
@updated-outputs)))))
100121

101122
(def options
102123
[["-n" "--num-operations NUM_OPS" "The number of elements that will be applied to the data structure"
103124
:default 100000
104125
:parse-fn #(Long. %)
105126
:validate [pos? "n must be positive"]]
106-
[nil "--data-structure" "Which data structure to run the test on"
127+
[nil "--data-structure STRUCT" "Which data structure to run the test on"
107128
:default "fractal"
108129
:validate [#(#{"fractal" "b-tree" "sorted-set"} %) "Data structure must be fractal, b-tree, or sorted set"]]
109130
[nil "--backend testing" "Runs the benchmark with the specified backend"
110131
:default "testing"
111132
:validate [#(#{"redis" "testing"} %) "Backend must be redis or testing"]]
133+
["-d" "--delete-pattern PATTERN" "Specifies how the operations will be reordered on delete"
134+
:default "forward"
135+
:validate [#(#{"forward" "reverse" "shuffle" "zero"} %) "Incorrect delete pattern"]
136+
]
112137
[nil "--sorted-set" "Runs the benchmarks on a sorted set"]
113138
["-b" "--tree-width" "Determines the width of the trees. Fractal trees use sqrt(b) child pointers; the rest is for messages."
114139
:default 300
@@ -138,35 +163,45 @@
138163
"Options:"
139164
options-summary
140165
""
166+
"Delete patterns:"
167+
"forward: we delete the elements in the order they were inserted"
168+
"reverse: we delete the elements in the reverse order they were inserted"
169+
"shuffle: we delete the elements in a random order"
170+
"zero: we repeatedly attempt to delete 0, thus never actually deleting"
171+
""
141172
"Backends:"
142173
"testing: this backend serializes nothing, just using an extra indirection"
143174
"redis: this backend uses a local redis server"]))
144175

145176
(defn make-template-for-one-tree-freq-combo
146-
[list-of-benchmark-results]
147-
(clojure.pprint/pprint list-of-benchmark-results)
177+
[list-of-benchmark-results filter-by]
178+
;(clojure.pprint/pprint list-of-benchmark-results)
148179
(assert (= 2 (count list-of-benchmark-results)) "Should be random and ordered")
149180
(let [indexed (group-by :ds list-of-benchmark-results)]
150-
(map #(vector (:n %1) (:avg-ns %1) (:writes %1) (:avg-ns %2) (:writes %2))
151-
(:results (first (get indexed "in-order")))
152-
(:results (first (get indexed "random"))))))
181+
(map #(vector (:n %1) (:ins-avg-ns %1) (:writes %1) (:ins-avg-ns %2) (:writes %2))
182+
(filter filter-by (:results (first (get indexed "in-order"))))
183+
(filter filter-by (:results (first (get indexed "random")))))))
153184

154185
(defn template-one-sheet
155186
[pair-of-results-for-one-ds-config]
156-
(let [{:keys [tree ds freq n b results]} (first pair-of-results-for-one-ds-config)
187+
(let [{:keys [tree ds freq n b results delete-pattern]}
188+
(first pair-of-results-for-one-ds-config)
157189
x {;:sheet-name (str (name tree) " " ds " flushed every " freq)
158190
0 [["Data Structure" (name tree) "" "n" n]]
159-
1 [["Flush Frequency" freq "" "b" b]]
160-
[5 104] (make-template-for-one-tree-freq-combo pair-of-results-for-one-ds-config)}]
191+
1 [["Flush Frequency" freq "" "b" b "" "delete pattern" delete-pattern]]
192+
[5 18] (make-template-for-one-tree-freq-combo pair-of-results-for-one-ds-config :insert)
193+
[22 35] (make-template-for-one-tree-freq-combo pair-of-results-for-one-ds-config :delete)}]
161194
x))
162195

163196
(defn -main
164197
[root & args]
165-
(doseq [args (->> args
166-
(partition-by #(= % "--"))
167-
(map-indexed vector)
168-
(filter (comp even? first))
169-
(map second))]
198+
(doseq [args (or (->> args
199+
(partition-by #(= % "--"))
200+
(map-indexed vector)
201+
(filter (comp even? first))
202+
(map second)
203+
(seq))
204+
[[]])] ; always do one iteration
170205
(let [{:keys [options arguments errors summary]} (parse-opts args options)
171206
tree-to-test (atom {})
172207
results (atom [])]
@@ -178,38 +213,49 @@
178213
"testing" (core/->TestingBackend)
179214
"redis" (redis/->RedisBackend
180215
#_(java.util.concurrent.Executors/newFixedThreadPool 4)))
216+
delete-xform (case (:delete-pattern options)
217+
"forward" identity
218+
"reverse" reverse
219+
"shuffle" shuffle
220+
"zero" #(repeat (count %) 0.0))
181221
[tree-name structure]
182222
(case (:data-structure options)
183223
"b-tree" ["b-tree" (core-b-tree (:tree-width options) backend)]
184224
"fractal" ["fractal" (msg-b-tree (:tree-width options) backend)]
185225
"sorted-set" ["sorted-set" (sorted-set-repr)])
186226
flush-freq (:flush-freq options)
187227
codename (str tree-name
188-
"_flush"
228+
"__flush_"
189229
flush-freq
190-
"_b"
230+
"__b_"
191231
(:tree-width options)
192-
"_"
232+
"__"
193233
(:backend options)
194-
"_n"
195-
(:num-operations options))]
234+
"__n_"
235+
(:num-operations options)
236+
"__del_"
237+
(:delete-pattern options))]
196238
(doseq [ds (generate-test-datasets)
197239
:let [codename (str codename
198240
"_"
199241
(:name ds))
200242
out (create-output-dir
201243
root
202-
codename)]]
203-
(println "Doing" codename)
244+
codename)
245+
_ (println "Doing" codename)
246+
bench-res (benchmark (:num-operations options) ds flush-freq structure out delete-xform)]]
204247
(swap! results conj
205248
{:tree tree-name
206249
:ds (:name ds)
207250
:freq flush-freq
208251
:n (:num-operations options)
209252
:b (:tree-width options)
210-
:results (benchmark (:num-operations options) ds flush-freq structure out)}))
211-
(excel/render-to-file
212-
"template_benchmark.xlsx"
213-
(.getPath (File. root (str codename "_analysis.xlsx")))
214-
{"SingleDS"
215-
(template-one-sheet @results)})))))
253+
:delete-pattern (:delete-pattern options)
254+
:results bench-res}))
255+
;(println "results")
256+
;(clojure.pprint/pprint @results)
257+
(excel/render-to-file
258+
"template_benchmark.xlsx"
259+
(.getPath (File. root (str codename "_analysis.xlsx")))
260+
{"SingleDS"
261+
(template-one-sheet @results)})))))

template_benchmark.xlsx

3.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)