Reporting issues in 1.5.2 (also, custom action example)

Hi all -
The reports from Gatling are sometimes not as expected.

First, back story:
I’m using Gatling for something where I need to do both HTTP requests using the built-in client, and do other request using a client Java API.
It took some time to figure out how (the wiki page on protocols helped a bit, but I could have used a complete example. If there are examples anywhere, I have missed them).

Anyway… below is a demo simulation. It performs a custom action. The action reports to the DataWriter that time-wise, all of its requests are identical: 1ms to send the request, 3ms latency, 12ms reponse transfer time.

The problem is that what is reported on the generated HTML page is min=10, max=20, avg=16ms.
The response time distribution shows one bar at 11ms and one at 20ms. The heights of these bars vary from run to run; they are both 40-60%. If I add a 10ms pause, the majority are at in the bar at 11ms.

Oh, I think I’ve got it:
if I multiply the delays by 10, I get the correct output: all requests at 160ms (but no R.T.D bar chart).
Is seems, then, that the millisecond timestamp values are for some reason divided (truncatingly) by 10 (the accuracy, in fact) before subtracting is done. Why is this?
One would expect bucketing done after subtraction. And one wouldn’t expect (executionStartDate % accuracy) to have any effect on the bucketing, but that’s the case now.
(I’m glad it’s not the concurrency bug I suspected, though.)

Also, surely the bar chart should not be blank even if min=max?

Regards,
Erik Søe Sørensen
[less confused now - bugs you understand are preferable to results that look random]

==== The simulation code ====

import com.excilys.ebi.gatling.core.Predef._
import com.excilys.ebi.gatling.http.Predef._
import com.excilys.ebi.gatling.jdbc.Predef._
import com.excilys.ebi.gatling.http.Headers.Names._
import akka.util.duration._
import bootstrap._
import assertions._
import java.util.Random
import java.net.URLEncoder

import com.excilys.ebi.gatling.core.action.{Action,SimpleAction, system}
import com.excilys.ebi.gatling.core.action.builder.ActionBuilder
import com.excilys.ebi.gatling.core.util.TimeHelper.nowMillis
import com.excilys.ebi.gatling.core.result.writer.DataWriter
import com.excilys.ebi.gatling.core.result.message.RequestStatus.{ KO, OK }
import akka.actor.{ ActorRef, Props }
import com.excilys.ebi.gatling.core.config.ProtocolConfigurationRegistry

class CustomActionSimulation extends Simulation {
val users = 100
val repetitions_per_user = 50
val users_per_second = 5

val httpConf = httpConfig.connection(“keep-alive”)

var scn = scenario(“Opret-fremsøg”)
.repeat(repetitions_per_user) {
exec(new MyActions.MyActionBuilder())
.pause(10 milliseconds)
}

setUp(scn.users(users).ramp(users / users_per_second).protocolConfig(httpConf))
}

object MyActions {
class MyAction(val next: ActorRef) extends Action {
def execute(session: Session) {
val t0 = nowMillis
val executionStartDate = t0
val requestSendingEndDate = t0+10
val responseReceivingStartDate = t0+40
val executionEndDate = t0+160
DataWriter.logRequest(session.scenarioName,
session.userId,
“TheRequest”,
executionStartDate,
requestSendingEndDate,
responseReceivingStartDate,
executionEndDate,
OK
)
next ! session
}
}

class MyActionBuilder(val next:ActorRef=null) extends ActionBuilder {
def withNext(next: ActorRef) = new MyActionBuilder(next)

def build(protocolConfigurationRegistry: ProtocolConfigurationRegistry): ActorRef = system.actorOf(Props(new MyAction(next)))
}
}

For performance reasons, times are rounded up when generating the reports.
The default value is 10 ms.
https://github.com/excilys/gatling/blob/master/gatling-bundle/src/main/assembly/assembly-structure/conf/gatling.conf#L52

Lower this value to 1 ms.

Cheers,

Stéphane

I understand the need for decreasing the number of buckets.
I just don’t see why the accuracy should be reduced before the time difference to bucketize is calculated?

The relevant code is afaict this:
val executionStart = reduceAccuracy((strings(4).toLong - runStart).toInt)
val requestEnd = reduceAccuracy((strings(5).toLong - runStart).toInt)
val responseStart = reduceAccuracy((strings(6).toLong - runStart).toInt)
val executionEnd = reduceAccuracy((strings(7).toLong - runStart).toInt)
val status = RequestStatus.withName(strings(8))
val executionStartBucket = bucketFunction(executionStart)
val executionEndBucket = bucketFunction(executionEnd)
val responseTime = reduceAccuracy(executionEnd - executionStart)
val latency = reduceAccuracy(responseStart - requestEnd)

I’d have expected something like this:

val executionStart = (strings(4).toLong - runStart).toInt
val requestEnd = (strings(5).toLong - runStart).toInt
val responseStart = (strings(6).toLong - runStart).toInt
val executionEnd = (strings(7).toLong - runStart).toInt
val status = RequestStatus.withName(strings(8))
val executionStartBucket = bucketFunction(reduceAccuracy(executionStart))
val executionEndBucket = bucketFunction(reduceAccuracy(executionEnd))
val responseTime = reduceAccuracy(executionEnd - executionStart)
val latency = reduceAccuracy(responseStart - requestEnd)

Hi Erik,

First, sorry for the late reply.
You’re right, and I’ll try to fix this ASAP (crashed my computer, have to reinstalled my 1.5 dev env yet).
We’ll probably rewrite this part in Gatling 2, even I am getting lost there…

Cheers,

Stéphane