diff options
| author | yo momma <shutup@oops.wtf> | 2026-02-04 19:25:03 +0000 |
|---|---|---|
| committer | yo momma <shutup@oops.wtf> | 2026-02-04 19:25:03 +0000 |
| commit | 75cf2a9c3cd925d2d8de4b5ef98bdd55c29e9861 (patch) | |
| tree | 457640db50cd62bac0649119abed37c3bdeb2fe7 /test/humpfm/millstone.clj | |
| parent | ad4d74ea45be6b227027588f6515fb22fafc335a (diff) | |
Rebrand: rename dump assets/templates to hump
Diffstat (limited to 'test/humpfm/millstone.clj')
| -rwxr-xr-x | test/humpfm/millstone.clj | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/test/humpfm/millstone.clj b/test/humpfm/millstone.clj new file mode 100755 index 0000000..095abed --- /dev/null +++ b/test/humpfm/millstone.clj @@ -0,0 +1,148 @@ +(ns humpfm.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)) + +(defn- success? [resp] + (= (:code resp) 200)) + +(defnk do-request! [path + :label nil + :params nil + :method "GET"] + (let [[ms resp] (with-timing + (try (do-base-request (:server *spec*) + path + method + *cookies* + params) + (catch Exception e + (log (format "Exception for %s - %s" path (.getMessage e))) + {:code "?" :msg "EXCEPTION"}))) + result {:path path + :label (or label path) + :ms ms + :error (if (success? resp) nil [(:code resp) (:msg resp)])}] + (if (= (rand-int 100) 1) + (log (format "%s - %.02fms" path ms))) + (dosync + (commute *results* conj result)) + resp)) + +(defn build-client! [spec client-id] + (binding [*cookies* {}] + (if (:setup-func spec) + ((:setup-func spec))) + {:client-id client-id + :cookies *cookies*})) + +(defn join [s lst] + (apply str (interpose s lst))) + +(defn sum [nums] + (reduce + nums)) + +(defn avg [nums] + (float (/ (sum nums) (count nums)))) + +(defn print-run-results [spec results elapsed-ms] + (log (format "\nResults\n--------\n%s requests in %.02fs (%.02f r/s)\n%s clients" + (count results) + (/ elapsed-ms 1000) + (/ (count results) (/ elapsed-ms 1000)) + (:clients spec))) + (let [avg-in-req (/ (sum (map :ms results)) (:clients spec))] + (log (format "\nTime spent in requests (per worker): %.02fs (%.02f%%)" + (/ avg-in-req 1000) + (* (/ avg-in-req elapsed-ms) 100)))) + (doseq [[label rs] (group-by :label results)] + (let [nums (map :ms rs) + errors (filter identity (map :error rs))] + (log (format "\n%s:\n#: %s\nmin: %.02f ms\navg: %.02f ms\nmax: %.02f ms" + label + (count rs) + (apply min nums) + (avg nums) + (apply max nums))) + (if-let [threshhold (:max-latency spec)] + (let [timeouts (count (filter #(> % threshhold) + (map :ms rs)))] + (if (not (zero? timeouts)) + (log (format "timeouts: %s (> %sms)" timeouts threshhold))))) + (if (not (empty? errors)) + (log (format "errors: %s (%s)" + (count errors) + (join " " (sort (set errors)))))))) + (log "")) + +(defn build-func-list [routes] + (flatten (for [[n f] routes] + (repeat n f)))) + +(def num-updates 10) + +(defn update-markers [reqs num] + (set (map #(int (* % (/ reqs num))) (range 1 (inc num))))) + +(defn grind! [spec] + (binding [*spec* spec] + (let [clients (doall + (for [id (range (:clients spec))] + (build-client! spec id))) + reqs (:requests spec) + funcs (build-func-list (:funcs spec)) + results (ref []) + counter (atom 0) + update-on (update-markers reqs num-updates) + threads (doall + (for [c clients] + (Thread. + (fn [] + (binding [*spec* spec + *cookies* (:cookies c) + *results* results] + (loop [] + (let [c (swap! counter inc)] + (if (<= c reqs) + (do ((rand-elt funcs)) + (if (contains? update-on c) + (log (format "Completed %s requests" c))) + (recur))))))))))] + (log "Finished setup") + (let [[elapsed _] (with-timing + (do + (doseq [t threads] + (.start t)) + (doseq [t threads] + (.join t))))] + (print-run-results spec @results elapsed))))) |
