Search code examples
restjmeterperformance-testingweb-api-testing

Concurrency in Apache JMeter load testing has strange behaviour


I'm doing some loadtesting of an API using a somewhat basic setup in JMeter.

The idea here is that the Thread group spawns a bunch of clients/threads and each of these clients has a bunch of loops which runs in parallel (using the Bzm - parallel controller).

Each loop represents some kind of action that a user can perform and each loop has a Uniform Timer Controller to adjust how often a given action is performed for each client.

One of the actions consists of two calls, first one (1) fetches som id's which are then extracted with a JSON extractor and modified a bit with a BeanShell Post Processor. The result from the post processor is then used as a param for the next call (2).

The issue I'm facing is that in my Summary report there is a lot more results from the first HTTP request (1) showing up than from the second one (2). I would expect them to always be called the same number of times.

My guess is that it all comes down to me lacking some basic understanding of flow and concurrency (and maybe timers) in JMeter, but I have been unable to figure it out, so I need help.

This is the setup, imagine there being multiple loops.

 Thread group
      +
      |
      +------ ---+ Parallel controller
      |                    +
      |                    |
      |                    +-----------+ Loop
      |                                   +
      |                                   +----------+ Transaction
      |                                   |                +
      |                                   |                |
      |                                   |                +---------+ Uniform random timer
      |                                   |                                    +
      |                                   |                                    |
      |                                   |                                    |
      |                                   |                                    +
      |                                   |                             (1) HTTP request
      |                                   |                                    +
      |                                   |                                    +---------+ JSON extractor
      +                                   |                                    |                +
                                          |                                    |                |
Summary Report                            |                                    |                +
                                          |                                    |       BeanShell Post processor
                                          |                                    |
                                          |                                    |
                                          |                                    |
                                          |                                    +
                                          |
                                          |                              (2) HTTP request
                                          |
                                          |
                                          |
                                        Loop +----------------------------------+
                                          |
                                          |
         

Solution

  • Ok, so I figured it out. It all comes down to understanding the structure of the tests, diving in to the docs really helped as they are very detailed.

    This is the relevant part:

    Note that timers are processed before each sampler in the scope in which they are found; if there are several timers in the same scope, all the timers will be processed before each sampler. Timers are only processed in conjunction with a sampler. A timer which is not in the same scope as a sampler will not be processed at all. To apply a timer to a single sampler, add the timer as a child element of the sampler. The timer will be applied before the sampler is executed. To apply a timer after a sampler, either add it to the next sampler, or add it as the child of a Flow Control Action Sampler.

    https://jmeter.apache.org/usermanual/component_reference.html#timers

    Another extremely important thing to understand is that some building blocks (in relation to the tree structure) are hierarchical some are ordered and some are both. This is described in detail here https://jmeter.apache.org/usermanual/test_plan.html#scoping_rules

    All in all my issue could be fixed by putting the Uniform random timer as a child of the first HTTP call (1) causing it to only affect that call, or by adding a Flow Control Action as a sibling after the second call (2) and adding the Uniform random timer as a child to that.