summaryrefslogtreecommitdiff
path: root/test/dumpfm/millstone.clj
blob: e6937291631e2fbb33fb62449600ae9fceedbb84 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
(ns dumpfm.millstone
  (:use clojure.contrib.def
	clojure.contrib.seq-utils
	clojure-http.client))

(def *spec*)
(def *cookies*)
(def *results*)

(def printer (agent nil))

(defn log [& args]
  (send printer (fn [_] (apply println args))))

(defmacro with-timing [e]
  `(let [s# (System/nanoTime)
         r# ~e
         f# (System/nanoTime)]
     [(float (/ (- f# s#) 1e6)) r#]))

(defn do-base-request [server path method cookies params]
  (let [method (.toUpperCase method)
	url    (str server path)]
    (if (= method "GET")
      (request (add-query-params url params) method nil cookies)
      (request url method nil cookies params))))

(defnk do-setup-request! [path
			  :params nil
			  :method "GET"]
  (let [res (do-base-request (:server *spec*) path method *cookies* params)]
    (if (:cookies res)
      (set! *cookies* (merge *cookies* (:cookies res))))
    res))

(defnk do-request! [path
		    :params nil
		    :method :GET]
  (let [[ms resp] (with-timing
		      (do-base-request (:server *spec*)
				       path
				       method
				       *cookies*
				       params))
	result      {:path       path
		     :ms         ms}]
    (dosync
     (commute *results* conj result))
    (if (:cookies resp)
      (log "should set cookies" (:cookies resp)))
    resp))

(defn build-client! [spec client-id]
  (binding [*cookies*   {}]
    (if (:setup-func spec)
      ((:setup-func spec)))
    {:client-id client-id
     :cookies   *cookies*}))

(defn sum [nums]
  (reduce + nums))

(defn avg [nums]
  (float (/ (sum nums) (count nums))))

(defn print-run-results [spec results elapsed-ms]
  (log (format "\nFinished\n--------\n%s requests in %.02f s (%.02f r/s)\n%s clients"
	       (:requests spec)
	       (/ elapsed-ms 1000)
	       (/ (:requests spec) (/ elapsed-ms 1000))
	       (:clients spec)))
  (doseq [[path rs] (group-by :path results)]
    (let [nums (map :ms rs)]
      (log (format "\n%s:\nmin: %.02f ms\navg: %.02f ms\nmax: %.02f ms"
		       path
		       (apply min nums)
		       (avg nums)
		       (apply max nums)))))
  (log ""))

(defn build-func-list [routes]
  (flatten (for [[n f] routes]
	     (repeat n f))))

(defn grind! [spec]
  (binding [*spec* spec]
    (let [clients (doall
		   (for [id (range (:clients spec))]
		     (build-client! spec id)))
	  funcs     (build-func-list (:funcs spec))
	  results   (ref [])
	  counter   (atom (:requests spec))
	  threads (doall
		   (for [c clients]
		     (Thread.
		      (fn []
			(binding [*spec*    spec
				  *cookies* (:cookies c)
				  *results* results]
			  (loop []
			    (if (> (swap! counter dec) 0)
			      (let [f (rand-elt funcs)]
				(f)
				(recur)))))))))]
      (println "Finished setup")
      (let [[elapsed _] (with-timing
			  (do
			    (doseq [t threads]
			      (.start t))
			    (doseq [t threads]
			      (.join t))))]
	(print-run-results spec @results elapsed)))))