mhjort / trombi

Load testing library for testing stateful apps with Clojure
Eclipse Public License 1.0
235 stars 19 forks source link

Grace period between steps in a simulation #19

Closed slipset closed 8 years ago

slipset commented 8 years ago

To simulate real usage by real users, it would be nice to be able to introduce some sort of grace-period between functions in the simulation

(gat/run-simulation
   [{:name "my stress test"
     :requests [{:name "welcome-page" :fn welcome-page }
                {:sleep :period 10} ; user waits 10 seconds before accessing the login page
                {:name "login-page" :fn login-page }]}] 1)

I guess one could also imagine something like:

(gat/run-simulation
   [{:name "my stress test"
     :requests [{:name "welcome-page" :fn welcome-page :sleep-after 10 } ; sleep 10 secs after this reqest
                {:name "login-page" :fn login-page :sleep-before 10 } ; sleep 10 secs before this request
]}] 1)
mhjort commented 8 years ago

I am working on something similar to that. Thanks for the suggestions. I think especially the latter example looks nice. I could go for that. However, instead of specifying sleep time directly as integer I think function would be more generic. Sometimes I have had a need to vary a sleep time for certain user groups. So it would look like this

:sleep-before (fn [ctx] (if (odd? (:user-id ctx)) 5 10)

And if you just want single number you could specify

:sleep-before (constantly 5)

What do you think?

slipset commented 8 years ago

A function is way more flexible. Wish I had thought about that :)

mhjort commented 8 years ago

I'm in a middle of bigger refactoring for next version 0.8.0. I will include this grace period support for that version. However, I still need some time to polish it for the proper release. In meanwhile, I released a version:

[clj-gatling "0.8-beta1"]

which supports sleep-before function. Do you have time to give it a try?

slipset commented 8 years ago

I’ll give it a spin, probably sometime during this week.

On 3. mai 2016, at 07.12, Markus Hjort notifications@github.com wrote:

I'm in a middle of bigger refactoring for next version 0.8.0. I will include this grace period support for that version. However, I still need some time to polish it for the proper release. In meanwhile, I released a version:

[clj-gatling "0.8-beta1"]

which supports sleep-before function. Do you have time to give it a try?

— You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub

sarudak commented 8 years ago

Would this also allow us to do ramping? I was looking into simulating it using this but it screws with the pretty result graphs

(defn delay-provider [num-delays max-delay](let [delay-chan %28chan%29] %28go %28loop [remaining-delays %28concat %28repeatedly num-delays #%28rand-int max-delay%29%29 %28repeat 0%29%29] %28>! delay-chan %28first remaining-delays%29%29 %28recur %28rest remaining-delays%29%29%29%29 delay-chan))

(def delay-chan (delay-provider 200 300))

(defn do-delay [callback context](Thread/sleep %28<!! delay-chan%29) (callback true context))

(gatling/run-simulation [{:name "Ramp up then hammer admin" :requests [{:name "Ramp up delay" :fn do-delay} {:name "Call Admin" :http admin-url}]}] 10 {:duration (t/minutes 1)})

mhjort commented 8 years ago

I think this doesn't help with ramping. I have typically solved that issue by just calling run-simulation method twice and then ignored the results of the first run. For example first run (ramping) with 10 users and then next one with real amount of users (e.g 100).

I do admit that this is not the nicest way to solve the issue. There should be a proper support for ramping in clj-gatling.

sarudak commented 8 years ago

Yeah. That technique doesn't easily let you see a smooth ramp up so you can know at what point your server stopped being able to keep up.

sarudak commented 8 years ago

Trying out the beta I'm getting errors trying to require it. I'm using boot repl so it may be environment issues but I'm getting

(set-env! :dependencies '[[cheshire "5.6.1"] [clj-http "3.0.1"] [clj-gatling "0.8-beta1"] [org.clojure/core.async "0.2.374"]])

(require '[cheshire.core :as json]) (require '[clj-http.client :as client]) (require '[clj-gatling.core :as gatling]) (require '[clj-time.core :as t]) (require '[clojure.core.async :refer [>! <! >!! <!! go chan buffer close! thread alts! alts!! timeout]]) clojure.lang.Compiler$CompilerException: java.lang.NoClassDefFoundError: clojure/lang/Tuple, compiling:(clj_gatling/report.clj:1:1) java.lang.NoClassDefFoundError: clojure/lang/Tuple java.lang.ClassNotFoundException: clojure.lang.Tuple

sarudak commented 8 years ago

Issue went away when I converted it to a real project. I was able to model ramping in using a sleep before on the first part of each scenario with a function that provides a smaller number each time it's called. Thanks!

mhjort commented 8 years ago

Great! I created a separate issue related ramp-up. See #20. Let's continue discussion there.

mhjort commented 8 years ago

There is only :sleep-before option but that could be used for sleeping after the step by specifying that to the next step.