Understanding Gatling request time measurement vs other tools

Hello Gatling people,

I was reading this group for quite a while as I am diving more into Gatling internals and finding the right injection profiles for my use cases.

Right now I am currently in charge of a project that migrates previous Locust scripts to Gatling, and I am finding the request time measurement very different. Apart from the fact that Locust is being used with closed profile (in this case, it is being used with 32 users looping to get to 400rps), it looks like from Locust the network latency is either not taken into account or is negligible.

As an example:

  • Gatling simulation that ramps to 32 users in 4 seconds,
  • Each user performs a forever loop with an HTTP call pausing for 1 second
  • This is throttled to 300rps and held for 4 minutes

I get 107 ms on 95th percentile in Gatling report, but around 25ms in Locust, 27ms in AppDynamics and, for both Gatling and rest of the tests, the server time moves from 22ms to 25ms. This is pretty consistent across tests.

Could you help me understand how Gatling measures timings? is it not reusing connections on closed profile? Any piece of documentation that helps me understand this difference?

I kept all the defaults in gatling.conf. Any guidance is much appreciated. Thank you

  • Gatling accounts for TCP connect and TLS handshake duration hen it needs to open a new connection.

  • AFAIK (I can be wrong, you should confirm with Locust people), Locust only has a global connection pool and shares connections amongst virtual users.

Thanks a lot Stephane. This definitely clarify some concepts to me. Regardless of this is appropriate or not, is there any way to mimic the shared connection pool in Gatling using a closed profile. The scenario looks like:


def getStrategyExec(id: String) = {
.post("/endpoint/" + id)
.body(StringBody(session => session.get(“payload”).as[String])).asJSON)

val feeder = separatedValues(payloadsFile, ‘;’, escapeChar = ‘\’, quoteChar = ‘’’).records.circular

// _* is used to adapt any sequence (Seq, Array, List, …) to be passed
// as a list of parameters instead of 1 parameter (varargs) to randomSwitch.
// This is like this because randomSwitch receives Tuple2[Double,ChainBuilder]* (varargs)

val allStrategiesWeighted = forever {
feed(feeder).randomSwitch(strategiesList: _*).pause(1 second)

// One user executes the scenario for the duration of the test, then finishes

val scn = scenario(“T-Rex Strategies - Load & Performance Test”)

rampUsers(users) over (rampUpTime seconds))).maxDuration(testDuration minutes)
.throttle(reachRps(targetRps) in (90 seconds),holdFor(testDuration minutes))


There’s a search box in our documentation, you should probably give it a try :wink: