Controlling reads/writes in API perftest

Hello list,

I have just discovered Gatling after doing crazy thing with jmeter+BSF and template jmx file that seems kindda cool but is too awkward after all :slight_smile:

I’m trying to figure out how can I control read/write ratio on per http-method basis, e.g. put:50% / get:35% / post: 15%

I have semi-crazy way of doing this in jmeter, but couldn’t see anything close to the “throughput controller”

Cheers,

Hi Ilya,

I’m not sure I get it right, sorry.

With Gatling you basically defined groups of users, maybe shape them with a ramp or a delay, and inject them in a kind of workflow.

Do your requests have to happen in a defined order for a given user or can you launch them randomly?

Cheers,

Stéphane

2012/9/6 Ilya Dmitrichenko <errordeveloper@gmail.com>

Stéphane,

Hey, perhaps using jmeter too much got me into some sort of
unnecessary complexity frame!

It now occurs to me that what I need can be done like this:

  val writerGuy = scenario("User who writes")
  val readerGuy = scenario("User who reads")

  val ourController = myUsersBehaveLikeThis(Integer.getInteger("max_users")

  List(
    writerGuy.configure.users(ourController.getNumOfReaders).ramp(ourController.getReadRamp).protocolConfig(httpConf),
    readerGuy.configure.users(ourController.getNumOfWriters).ramp(ourController.getWriteRamp).protocolConfig(httpConf)
   )

And we should be fine with that, once `myUsersBehaveLikeThis` is defined :slight_smile:

Cheers,

I’m still unsure how you intend to “feed” your scenario with the requests.

Let’s say you want to test the operations of a given REST webservice, so you know beforehand the structure of the data you have to pass and are able to write the requests with the Gatling DSL.

In the upcoming 1.3.0, you’ll have a randomSwitch, so you can write something like that:

val scn = scenario(“myWebservice”)
.randomSwitch {
50 → exec(myPutRequest),
35 → exec(myGetRequest),
15 → exec(myPostRequest)
}

Would that help?

Stéphane

2012/9/6 Ilya Dmitrichenko <errordeveloper@gmail.com>

Ah ah, I just replied to you.

Yes, you probably need a mind shift when coming from JMeter.
Segregating operation types into different population is another way to do it too.

2012/9/7 Ilya Dmitrichenko <errordeveloper@gmail.com>

Yes! That will also solve one of my other problems!!

In 1.3.0, you’ll also have randomSwitch without percentages (equally distributed) and roundRobinSwitch.

So if you have several requests per type, you could write:

val putRequests = roundRobinSwitch(putRequest1, putRequest2…)
val getRequests = roundRobinSwitch(getRequest1, getRequest2…)
val postRequests = roundRobinSwitch(postRequest1, postRequest2…)

val scn = scenario(“myWebservice”)
.randomSwitch {
50 → putRequests,
35 → getRequests,
15 → postRequests
}

2012/9/7 Ilya Dmitrichenko <errordeveloper@gmail.com>

Stéphane, thanks!

Looks like `randomSwitch` is in HEAD already, is it complete?

Cheers,

Depends on your complete definition. 328.png

Yep, it’s developed and refactored, Nicolas has played with it a little bit and it seems to work fine, but it hasn’t be extensively tested yet.

2012/9/7 Ilya Dmitrichenko <errordeveloper@gmail.com>

Ok, I’ll give it ago and keep you posted :slight_smile:

328.png

Cool, thanks!

2012/9/7 Ilya Dmitrichenko <errordeveloper@gmail.com>

328.png

Hey,

I have managed to use randomSwitch like this:

https://gist.github.com/3690803

But after I pulled master, I get this error:

[INFO] — gatling-maven-plugin:1.3.0-SNAPSHOT:execute (default-cli) @ api-load-test —
[INFO] Exception in thread “main” java.lang.RuntimeException: Compilation failed:
[INFO] /home/ilya/gatling_work/tests/TestRandomController.scala:21: error: overloaded method value randomSwitch with alternatives:
[INFO] (possibility1: com.excilys.ebi.gatling.core.structure.ChainBuilder,possibility2: com.excilys.ebi.gatling.core.structure.ChainBuilder,possibilities: com.excilys.ebi.gatling.core.structure.ChainBuilder*)com.excilys.ebi.gatling.core.structure.ScenarioBuilder
[INFO] (possibility1: (Int, com.excilys.ebi.gatling.core.structure.ChainBuilder),possibility2: (Int, com.excilys.ebi.gatling.core.structure.ChainBuilder),possibilities: (Int, com.excilys.ebi.gatling.core.structure.ChainBuilder)*)com.excilys.ebi.gatling.core.structure.ScenarioBuilder
[INFO] cannot be applied to ((Int, com.excilys.ebi.gatling.core.structure.ChainBuilder))
[INFO] .randomSwitch {
[INFO] ^
[INFO] one error found
[INFO]
[INFO] at com.excilys.ebi.gatling.app.SimulationClassLoader$$anonfun$fromSourcesDirectory$1.apply(SimulationClassLoader.scala:63)
[INFO] at com.excilys.ebi.gatling.app.SimulationClassLoader$$anonfun$fromSourcesDirectory$1.apply(SimulationClassLoader.scala:53)
[INFO] at com.excilys.ebi.gatling.core.util.IOHelper$.use(IOHelper.scala:24)
[INFO] at com.excilys.ebi.gatling.app.SimulationClassLoader$.fromSourcesDirectory(SimulationClassLoader.scala:53)
[INFO] at com.excilys.ebi.gatling.app.Gatling$$anonfun$11$$anonfun$13.apply(Gatling.scala:79)
[INFO] at com.excilys.ebi.gatling.app.Gatling$$anonfun$11$$anonfun$13.apply(Gatling.scala:79)
[INFO] at scala.Option.getOrElse(Option.scala:108)
[INFO] at com.excilys.ebi.gatling.app.Gatling$$anonfun$11.apply(Gatling.scala:79)
[INFO] at com.excilys.ebi.gatling.app.Gatling$$anonfun$11.apply(Gatling.scala:75)
[INFO] at scala.Option.getOrElse(Option.scala:108)
[INFO] at com.excilys.ebi.gatling.app.Gatling.start(Gatling.scala:75)
[INFO] at com.excilys.ebi.gatling.app.Gatling$.fromMap(Gatling.scala:64)
[INFO] at com.excilys.ebi.gatling.app.Gatling$.main(Gatling.scala:59)
[INFO] at com.excilys.ebi.gatling.app.Gatling.main(Gatling.scala)

So I figured the changes had been made since my last checkout …

Is this a bug or I’m supposed to use it differently?

Cheers,

Hi,

I think that you are just missing some comas in the tuples you’re providing in randomSwitch(), see https://gist.github.com/3691602

is it working ?

cheers
Nicolas

Sure, it does :slight_smile:

So the original example (above in this thread) wasn't quite right:
  val scn = scenario("myWebservice")
    .randomSwitch {
      50 -> exec(myPutRequest),
      35 -> exec(myGetRequest),
      15 -> exec(myPostRequest)
     }

Though it worked when I removed the comas (cause the error it gave
seemed like the issue is with that) and it seemed to work then :slight_smile:

hm ... so far it looks like the syntax-related error message from
scala are rather hard to figure out ;(
I presume that Gatling DSL makes it a bit worse ... may be some sort
of basic linter would help at this stage? or users do get used to it
after a while?

Hi Ilya,

Please understand that you’re walking on the wild side, here, not knowing any scala and using features that have not been documented yet…

The compilation error is actually quite clear when you know the API and a bit of Scala.

First of all, key → value is a Scala syntactic sugar for a Tuple2.

randomSwitch is indeed overloaded:

  • randomSwitch((Int, ChainBuiler), (Int, ChainBuiler), (Int, ChainBuiler)*)
  • randomSwitch(ChainBuiler, ChainBuiler, ChainBuiler*)

The second one is a variation of the first one, but with an homogeneous distribution.

Why all there parameters? So that you can’t build a switch with less that 2 alternatives.

The compiler was complained that your arguments didn’t match any of theses signatures.

Hopefully things will get clearer with the upcoming documentation.
Until then, feel free to ask.

Cheers,

Stéphane

2012/9/10 Ilya Dmitrichenko <errordeveloper@gmail.com>

Stéphane, Nicolas, thanks :slight_smile: