]>
Commit | Line | Data |
---|---|---|
e59229a2 | 1 | |
2 | ||
3 | (add-classpath "file:///Users/ragge/Projects/clojure/redis-clojure/redis-clojure.jar") | |
4 | ||
5 | (ns benchmarks.clojure | |
6 | (:use clojure.contrib.pprint) | |
7 | (:require redis)) | |
8 | ||
9 | (defstruct benchmark-options | |
10 | :host | |
11 | :port | |
12 | :db | |
13 | :clients | |
14 | :requests | |
15 | :key-size | |
16 | :keyspace-size | |
17 | :data-size) | |
18 | ||
19 | ||
20 | (defstruct client | |
21 | :id | |
22 | :request-times | |
23 | :requests-performed | |
24 | :requests-per-second) | |
25 | ||
26 | (defstruct result | |
27 | :options | |
28 | :clients | |
29 | :total-time | |
30 | :requests) | |
31 | ||
32 | ||
e59229a2 | 33 | (defmacro defbenchmark [name & body] |
34 | (let [benchmark-name (symbol (str name "-benchmark"))] | |
35 | `(def ~(with-meta benchmark-name {:benchmark true}) | |
36 | (fn ~benchmark-name | |
37 | [client# options# result#] | |
38 | (redis/with-server | |
39 | {:host (options# :host) | |
40 | :port (options# :port) | |
41 | :db (options# :db)} | |
42 | (let [requests# (:requests options#) | |
43 | requests-done# (:requests result#)] | |
44 | (loop [requests-performed# 0 request-times# []] | |
45 | (if (>= @requests-done# requests#) | |
46 | (assoc client# | |
47 | :request-times request-times# | |
48 | :requests-performed requests-performed#) | |
49 | (do | |
50 | (let [start# (System/nanoTime)] | |
51 | ~@body | |
52 | (let [end# (System/nanoTime) | |
53 | elapsed# (/ (float (- end# start#)) 1000000.0)] | |
54 | (dosync | |
55 | (commute requests-done# inc)) | |
56 | (recur (inc requests-performed#) | |
57 | (conj request-times# elapsed#))))))))))))) | |
58 | ||
59 | (defbenchmark ping | |
60 | (redis/ping)) | |
61 | ||
62 | (defbenchmark get | |
63 | (redis/get (str "key-" (rand-int 1000)))) | |
64 | ||
65 | (defbenchmark set | |
111d9959 | 66 | (redis/set (str "key-" (rand-int 1000)) "abc")) |
e59229a2 | 67 | |
68 | (defbenchmark exists-set-and-get | |
69 | (let [key (str "key-" (rand-int 100))] | |
70 | (redis/exists key) | |
71 | (redis/set key "blahongaa!") | |
72 | (redis/get key))) | |
73 | ||
74 | ||
75 | (def *default-options* (struct-map benchmark-options | |
76 | :host "127.0.0.1" | |
77 | :port 6379 | |
78 | :db 15 | |
111d9959 | 79 | :clients 1 |
e59229a2 | 80 | :requests 10000)) |
81 | ||
82 | (defn create-clients [options] | |
83 | (for [id (range (:clients options))] | |
84 | (agent (struct client id)))) | |
85 | ||
86 | (defn create-result [options clients] | |
87 | (let [result (struct result options clients 0 (ref 0))] | |
88 | result)) | |
89 | ||
90 | ||
91 | (defn requests-by-ms [clients] | |
92 | (let [all-times (apply concat (map #(:request-times (deref %)) clients)) | |
93 | all-times-in-ms (map #(int (/ % 1)) all-times)] | |
94 | (sort | |
95 | (reduce | |
96 | (fn [m time] | |
97 | (if (m time) | |
98 | (assoc m time (inc (m time))) | |
99 | (assoc m time 1))) | |
100 | {} all-times-in-ms)))) | |
101 | ||
102 | (defn report-request-times [clients requests] | |
103 | (let [requests-dist (map #(let [perc (* 100 (/ (last %) requests))] | |
104 | (conj % perc)) (requests-by-ms clients))] | |
111d9959 | 105 | (loop [items requests-dist |
106 | seen 0] | |
107 | (if-not (empty? items) | |
108 | (do | |
109 | (let [item (first items) | |
110 | seen (+ seen (last item))] | |
111 | (println (format "%.2f%% < %d ms" (float seen) (inc (first item)))) | |
112 | (recur (rest items) seen))))))) | |
e59229a2 | 113 | |
114 | (defn report-client-rps [client] | |
115 | (let [{:keys [id requests-performed request-times]} @client] | |
116 | (when (< 0 requests-performed) | |
117 | (let [total-time (apply + request-times) | |
118 | requests-per-second (/ (float requests-performed) | |
119 | total-time)] | |
120 | (println total-time) | |
121 | (println (format "Client %d: %f rps" id (float requests-per-second))))))) | |
122 | ||
123 | (defn report-result [result] | |
124 | (let [{:keys [clients options]} result | |
125 | name (:name result) | |
126 | time (:total-time result) | |
127 | time-in-seconds (/ time 1000) | |
128 | requests (deref (:requests result)) | |
129 | requests-per-second (/ requests time-in-seconds) | |
130 | ] | |
131 | (do | |
132 | (println (format "====== %s =====\n" name)) | |
133 | (println (format " %d requests completed in %f seconds\n" requests time-in-seconds)) | |
134 | (println (format " %d parallel clients\n" (:clients options))) | |
111d9959 | 135 | (report-request-times clients requests) |
e59229a2 | 136 | ;(dorun (map report-client-rps clients)) |
137 | (println (format "%f requests per second\n\n" requests-per-second)) | |
138 | ) | |
139 | ) | |
140 | ) | |
141 | ||
142 | ||
143 | ||
144 | (defn run-benchmark [fn options] | |
145 | (let [clients (create-clients options) | |
146 | result (create-result options clients) | |
147 | start (System/nanoTime)] | |
148 | (dorun | |
149 | (map #(send-off % fn options result) clients)) | |
150 | (apply await clients) | |
151 | (let [elapsed (/ (double (- (System/nanoTime) start)) 1000000.0)] | |
152 | (dorun | |
153 | (map #(when (agent-errors %) | |
154 | (pprint (agent-errors %))) clients)) | |
155 | (assoc result | |
156 | :name (str fn) | |
157 | :options options | |
158 | :clients clients | |
159 | :total-time elapsed)))) | |
160 | ||
161 | (defn find-all-benchmarks [ns] | |
162 | (filter #(:benchmark (meta %)) | |
163 | (vals (ns-map ns)))) | |
164 | ||
165 | (defn run-and-report [fn options] | |
166 | (let [result (run-benchmark fn options)] | |
167 | (report-result result))) | |
168 | ||
169 | (defn run-all-benchmarks [ns] | |
170 | (let [benchmarks (find-all-benchmarks ns)] | |
171 | (dorun | |
172 | (map #(run-and-report % *default-options*) benchmarks)))) | |
173 | ||
174 | ||
175 | ;(run-all-benchmarks) | |
176 | ||
177 | ;(report-result (run-benchmark ping-benchmark *default-options*)) | |
178 | ;(run-benchmark get-benchmark *default-options*) | |
179 |