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