The web service is written in Kotlin/Quarkus and uses MongoDB as a database.
The database stores Person
entities, each include a firstName
and lastName
field. Each time the web service is started, it defines a
pool of first and last names, and uses it to randomly create and store a number of Person
entities.
Total size of a pool is determined by app.entity-count
property in application.yml
file or APP_ENTITY_COUNT
environment variable.
The count of pre-generated entities is determined by prepopulate-percentage
property in application.yml
file
or APP_PREPOPULATE_PERCENTAGE
environment variable.
In my local setup, I use 100_000 entities in the pool and 70% of them are pre-populated in the database.
The load is generated by siege
which uses two endpoints:
GET /person/random
- gets a random first and last name from the pool and searches the database for a person with these names. If the person is found, it is returned with response code200
, if not,204
is returned.POST /person/random
- creates a new person with a random first and last name from the pool and saves it to the database. The response code is always200
.
Apart from 'random' endpoints used to simplify a load testing, there are regular endpoints, referenced in the test.http file.
During the load testing, the siege file urls-benchmark.txt is used to generate a preferred load with 5:1 Read/Write ratio. The urls-warmup.txt file may be used to warm up the database before the load testing.
# Use image from Docker Hub
docker-compose up -d
# Run load test
siege -c 50 -t 5m -b -i -f urls-benchmark.txt
The project Requires Java 17+ to build.
./gradlew build && \
docker build -f src/main/docker/Dockerfile -t ssamoilenko/hsal5-stress-test
You can also run application in dev mode that enables live coding using:
./gradlew quarkusDev
The results of load test with different number of concurrent users are located in the results folder.
Summary of the results:
Concurrency: | 10 | 25 | 50 | 100 | 200 | 400 | 800 | 1000 |
---|---|---|---|---|---|---|---|---|
Transactions | 3434 | 4428 | 3106 | 2713 | 2113 | 2324 | 1879 | 1756 |
Availability, % | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 | 100.00 |
Elapsed time, secs | 300.15 | 300.40 | 300.99 | 300.15 | 300.45 | 300.79 | 300.96 | 300.37 |
Data transferred, MB | 6.94 | 8.90 | 6.22 | 5.72 | 4.33 | 4.62 | 3.76 | 3.67 |
Response time, secs | 0.87 | 1.69 | 4.82 | 10.62 | 26.15 | 47.49 | 100.36 | 128.88 |
Transaction rate, trans/sec | 11.44 | 14.74 | 10.32 | 9.04 | 7.03 | 7.73 | 6.24 | 5.85 |
Concurrency | 9.99 | 24.93 | 49.74 | 95.95 | 183.93 | 366.95 | 626.58 | 753.46 |
Successful transactions | 3434 | 4428 | 3106 | 2713 | 2113 | 2324 | 1879 | 1756 |
Failed transactions | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Longest transaction, secs | 9.68 | 8.08 | 19.11 | 32.48 | 62.74 | 115.55 | 162.22 | 222.23 |
Shortest transaction, secs | 0.00 | 0.00 | 0.01 | 0.00 | 0.14 | 1.94 | 4.39 | 2.74 |