more stuff

This commit is contained in:
didier amyot committed 2018-07-01 15:14:28 -04:00
1 parent d22f0515d5
commit f93a09d2fe
6 files changed
+190 -11

No files matched your search

+116
View File
@@ -0,0 +1,116 @@
(ns skirmish.cli.benchmark
(:require [clojure.math.combinatorics :refer [cartesian-product]]
[clojure.core.async :refer [go chan <! >! close! to-chan close!] :as async]
[gniazdo.core :as ws]
[clj-http.client :as client]
[com.stuartsierra.frequencies :as freq]
[clojure.edn :as edn]))
(def ids (atom 0))
(defn web-socket-to-channel [url output-ch]
(let [on-receive #(go (>! output-ch %))
headers {"accept" "application/edn"}]
(ws/connect url :headers headers :on-receive on-receive)))
(defn create-trades-channel [securities]
(let [output (chan 1 (map edn/read-string))
url #(format "ws://localhost:%s/api/1/securities/%s/trades" 8080 %)
xf (comp (map :sec-id)
(map name)
(map url)
(map #(web-socket-to-channel % output)))]
(doall (sequence xf securities))
(async/pub output :book.order/order-id)))
(defn create-orders-channel [securities]
(let [output (chan 1 (map edn/read-string))
url #(format "ws://localhost:%s/api/1/securities/%s/orders" 8080 %)
xf (comp (map :sec-id)
(map name)
(map url)
(map #(web-socket-to-channel % output)))]
(doall (sequence xf securities))
(async/pub output :book.order/id)))
(defn create-requests-payload-for-security [i security id]
(let [rd (new java.util.Random i)
rand-bool (= (mod (. rd nextInt) 2) 0) ;; java random number generator REALLY sucks
type (if rand-bool :sell :buy)
price (+ (* 3 (. rd nextGaussian)) 30)
int-price (int (* price 100))
quantity (reduce + 1 (map #(. rd nextInt (inc %)) (range 100)))]
{:type type :quantity quantity :price int-price :security security :benchmark/id id}))
(defn create-requests-for-security [[i security]]
(let [req-id (swap! ids inc)
payload (create-requests-payload-for-security i (str (:sec-id security)) req-id)
sec-id-str (-> security :sec-id name)
params {:throw-exceptions false :content-type :edn :headers {"accept" "application/edn"}}
url (format "http://localhost:%s/api/1/securities/%s" 8080 sec-id-str)]
(fn []
(let [now (System/nanoTime)]
(client/post url (assoc params :form-params (assoc payload :benchmark/request-time now)))))))
(defn make-requests [n securities]
(map create-requests-for-security (cartesian-product (range n) securities)))
(defn no-more-then-n-simultaneously [f input-chan n]
(let [buffer (chan)]
(go (async/pipeline n buffer (map f) input-chan))
buffer))
(defn decode-response [response]
(let [now (System/nanoTime)
ret {}
ret (assoc ret :status (:status response))
ret (assoc ret :order (edn/read-string (:body response)))
ret (assoc ret :duration (/ (- now (get-in ret [:order :benchmark/request-time])) (Math/pow 10 9)))]
ret))
(defn benchmark [requests order trades]
(let [decoded-responses (chan 1 (map decode-response))
responses (no-more-then-n-simultaneously #(%) (to-chan requests) 10)]
(go (async/pipe responses decoded-responses))
decoded-responses))
(defn compute-result [results new-result]
(let [status-code (:status new-result)
duration (:duration new-result)
old-status-code-count (get-in results [:status status-code] 0)
ret results
ret (assoc-in ret [:status status-code] (inc old-status-code-count))
ret (assoc ret :durations (conj (:durations ret) duration))]
ret))
(defn pp-durations [durations]
(let [freq-map (frequencies durations)]
(print (freq/stats freq-map))))
(defn display-results [results]
(println results)
(println "number of request: " (:n results))
(println "status map: " (:status results))
(pp-durations (:durations results)))
(defn -main [config]
(let [benchmark-config (:benchmark config)
requests (-> benchmark-config :number-of-requests-per-securities (make-requests (:securities config)))
trades (create-trades-channel (:securities config))
orders (create-orders-channel (:securities config))
results (benchmark requests orders trades)]
(display-results (async/<!! (async/reduce compute-result {} results)))))
+3 -1
View File
@@ -1,10 +1,12 @@
(ns skirmish.core
(:require [skirmish.cli.core]
[skirmish.rest.core]
[skirmish.cli.benchmark]
[aero.core :refer (read-config)])
(:gen-class))
(def apps {:webserver skirmish.rest.core/-main})
(def apps {:webserver skirmish.rest.core/-main
:benchmark skirmish.cli.benchmark/-main})
(defn -main [& argv]
(let [config (-> "config.edn" clojure.java.io/resource read-config)
+13 -1
View File
@@ -1 +1,13 @@
(ns skirmish.rest.marketdata)
(ns skirmish.rest.marketdata
(:require [compojure.core :refer :all]))
(defn create-routes [exchange-apis]
(routes
(context "/api/1" []
(GET "/securities" [] )
(GET "/securities/:sec-id" [] (get-security exchange-apis))
(POST "/securities/:sec-id" [] (create-order exchange-apis))
(GET "/securities/:sec-id/trades" [] (listen-to-trades exchange-apis))
(GET "/securities/:sec-id/orders" [] (listen-to-orders exchange-apis)))
(not-found "not found")))