Skip to content

Load Testing

Systems

The following system was used for the performance evaluation:

SystemProviderCPUCoresRAMSSD
A5N46on-premRyzen 9900X2496 GiB4 TB Samsung 990 Pro
LEA47on-premEPYC 7543P16128 GiB3.2 TB Intel P5600 over vSAN
LEA79on-premEPYC 9555128768 GiB12.8 TB Huawei OceanDisk 300P

All systems were configured according to the Production Configuration guide. Deviating from it, all runs on all systems use a DB_RESOURCE_STORE_KV_THREADS of 64 instead of the default of 4. That variable sizes the thread pool the resource store uses to read and write resources and so caps how many resources can be written to the resource database at the same time. RocksDB merges concurrent writers into group commits: the writers waiting at any moment are batched into a single write-ahead log write followed by a single fsync, so the cost of that fsync — which dominates a write on systems with slow syncs — is shared by the whole group. With only four threads, at most four resources can join a group, whereas 64 threads allow much larger groups and so a considerably higher write throughput.

Datasets

The following datasets were used:

DatasetHistory# Pat. ¹# Res. ²# Obs. ³Size on SSD
1M10 years1 M1044 M593 M1045 GiB

¹ Number of Patients, ² Total Number of Resources, ³ Number of Observations

Methods

The load testing tool k6 is used to create load from another host in the same network as the test system.

Each test is a k6 script in the load-testing directory and is run via the Makefile. The FHIR base URL of the system under test — for example a Blaze running in a Docker container — is passed via the BASE environment variable:

sh
BASE=http://localhost:8080/fhir k6 run transaction.js

The optional DURATION environment variable (default 60 s) sets how long each concurrency level runs.

Single Patient Reads

Results

DatasetSystemVUsReq/smedq95q99
1MA5N46114050.500.741.47
1MA5N46239070.450.570.67
1MA5N46472480.530.590.69
1MA5N468133810.550.670.88
1MA5N4616236780.600.821.21
1MA5N4632383140.731.131.90
1MA5N4648456790.891.583.22
1MA5N4664488681.072.204.12

Patient Everything

Results

DatasetSystemVUsReq/smedq95q99
1MA5N46140.5015.728.354.7
1MA5N46273.0716.931.741.7
1MA5N464162.921.942.359.0
1MA5N468234.930.560.190.2
1MA5N4616261.257.698.7125.1
1MA5N4632258.7119.4174.3202.1

Transaction

This write test measures the throughput and latency of small FHIR transactions.

The transaction.js script repeatedly POSTs a small transaction bundle to the FHIR base URL. Each bundle creates one Patient and one Observation, where the Observation references the Patient via a bundle-internal URN, so reference resolution is exercised as well. The Patient's birthDate and the Observation's systolic blood pressure are randomized per transaction, so the date and quantity search-param indices see a realistic spread of values instead of a single repeated entry. New resources are created on every request, so the database grows over the course of the run.

All runs start from an empty database and grow it with every request, so there is no fixed dataset. The test was run on three systems to show how strongly transaction throughput depends on disk performance (see Disk Performance): LEA79 stores its data on a local NVMe disk with an fsync latency of a few microseconds, LEA47 accesses its disk over vSAN with an fsync latency of about 2 ms, and A5N46 uses a local consumer NVMe SSD that acknowledges a sync only once the data has reached the flash, at about 5 ms.

Results

SystemVUsReq/smedq95q99
LEA471129.66.578.8312.37
LEA472266.36.358.7213.37
LEA474399.89.2813.3220.61
LEA478420.719.3627.1134.98
LEA4716404.840.7157.7771.40
LEA4732443.646.83184.06217.65
LEA4764452.2119.24344.03433.56
LEA79112820.530.620.68
LEA79225350.520.680.84
LEA79446390.580.780.92
LEA79854081.211.421.54
LEA791652912.793.163.39
LEA793253105.956.637.15
LEA7964561711.6212.9615.64
A5N46187.7010.6014.1115.09
A5N462106.119.2826.6627.55
A5N46493.9739.1753.7154.47
A5N46895.0578.22105.84106.86
A5N461696.95156.61209.35212.69
A5N4632145.781.68569.79693.27
A5N4664162.6244.231430.351780.56

At high concurrency LEA47 plateaus around 450 transactions/s — close to its measured fsync rate of 479/s — because every transaction must durably persist its write to disk before responding, whereas LEA79 sustains over 5000 transactions/s.

LEA47:

Line chart. Transaction (LEA47). Concurrent Clients from 1 to 64. Left axis Requests/s: Requests/s. Right axis Processing Time (ms): Median RT, P95 RT, P99 RT.Transaction (LEA47)010020030040050001002003004005001248163264Concurrent Clients 1 · Requests/s: 129.567Concurrent Clients 2 · Requests/s: 266.283Concurrent Clients 4 · Requests/s: 399.75Concurrent Clients 8 · Requests/s: 420.733Concurrent Clients 16 · Requests/s: 404.8Concurrent Clients 32 · Requests/s: 443.6Concurrent Clients 64 · Requests/s: 452.217Concurrent Clients 1 · Median RT: 6.567 msConcurrent Clients 2 · Median RT: 6.349 msConcurrent Clients 4 · Median RT: 9.28 msConcurrent Clients 8 · Median RT: 19.36 msConcurrent Clients 16 · Median RT: 40.709 msConcurrent Clients 32 · Median RT: 46.832 msConcurrent Clients 64 · Median RT: 119.237 msConcurrent Clients 1 · P95 RT: 8.832 msConcurrent Clients 2 · P95 RT: 8.716 msConcurrent Clients 4 · P95 RT: 13.315 msConcurrent Clients 8 · P95 RT: 27.115 msConcurrent Clients 16 · P95 RT: 57.774 msConcurrent Clients 32 · P95 RT: 184.064 msConcurrent Clients 64 · P95 RT: 344.032 msConcurrent Clients 1 · P99 RT: 12.367 msConcurrent Clients 2 · P99 RT: 13.366 msConcurrent Clients 4 · P99 RT: 20.611 msConcurrent Clients 8 · P99 RT: 34.976 msConcurrent Clients 16 · P99 RT: 71.397 msConcurrent Clients 32 · P99 RT: 217.648 msConcurrent Clients 64 · P99 RT: 433.56 msRequests/sProcessing Time (ms)Concurrent ClientsRequests/sMedian RTP95 RTP99 RT

LEA79:

Line chart. Transaction (LEA79). Concurrent Clients from 1 to 64. Left axis Requests/s: Requests/s. Right axis Processing Time (ms): Median RT, P95 RT, P99 RT.Transaction (LEA79)010002000300040005000600002468101214161248163264Concurrent Clients 1 · Requests/s: 1282.433Concurrent Clients 2 · Requests/s: 2535.167Concurrent Clients 4 · Requests/s: 4639.15Concurrent Clients 8 · Requests/s: 5407.733Concurrent Clients 16 · Requests/s: 5290.583Concurrent Clients 32 · Requests/s: 5310.367Concurrent Clients 64 · Requests/s: 5617.333Concurrent Clients 1 · Median RT: 0.53 msConcurrent Clients 2 · Median RT: 0.521 msConcurrent Clients 4 · Median RT: 0.581 msConcurrent Clients 8 · Median RT: 1.212 msConcurrent Clients 16 · Median RT: 2.791 msConcurrent Clients 32 · Median RT: 5.95 msConcurrent Clients 64 · Median RT: 11.621 msConcurrent Clients 1 · P95 RT: 0.62 msConcurrent Clients 2 · P95 RT: 0.68 msConcurrent Clients 4 · P95 RT: 0.783 msConcurrent Clients 8 · P95 RT: 1.42 msConcurrent Clients 16 · P95 RT: 3.164 msConcurrent Clients 32 · P95 RT: 6.63 msConcurrent Clients 64 · P95 RT: 12.961 msConcurrent Clients 1 · P99 RT: 0.68 msConcurrent Clients 2 · P99 RT: 0.843 msConcurrent Clients 4 · P99 RT: 0.92 msConcurrent Clients 8 · P99 RT: 1.536 msConcurrent Clients 16 · P99 RT: 3.393 msConcurrent Clients 32 · P99 RT: 7.151 msConcurrent Clients 64 · P99 RT: 15.638 msRequests/sProcessing Time (ms)Concurrent ClientsRequests/sMedian RTP95 RTP99 RT

A5N46:

Line chart. Transaction (A5N46). Concurrent Clients from 1 to 64. Left axis Requests/s: Requests/s. Right axis Processing Time (ms): Median RT, P95 RT, P99 RT.Transaction (A5N46)05010015020005001000150020001248163264Concurrent Clients 1 · Requests/s: 87.7Concurrent Clients 2 · Requests/s: 106.117Concurrent Clients 4 · Requests/s: 93.967Concurrent Clients 8 · Requests/s: 95.05Concurrent Clients 16 · Requests/s: 96.95Concurrent Clients 32 · Requests/s: 145.717Concurrent Clients 64 · Requests/s: 162.55Concurrent Clients 1 · Median RT: 10.603 msConcurrent Clients 2 · Median RT: 19.283 msConcurrent Clients 4 · Median RT: 39.17 msConcurrent Clients 8 · Median RT: 78.215 msConcurrent Clients 16 · Median RT: 156.609 msConcurrent Clients 32 · Median RT: 81.681 msConcurrent Clients 64 · Median RT: 244.235 msConcurrent Clients 1 · P95 RT: 14.11 msConcurrent Clients 2 · P95 RT: 26.662 msConcurrent Clients 4 · P95 RT: 53.713 msConcurrent Clients 8 · P95 RT: 105.843 msConcurrent Clients 16 · P95 RT: 209.353 msConcurrent Clients 32 · P95 RT: 569.789 msConcurrent Clients 64 · P95 RT: 1430.35 msConcurrent Clients 1 · P99 RT: 15.087 msConcurrent Clients 2 · P99 RT: 27.551 msConcurrent Clients 4 · P99 RT: 54.467 msConcurrent Clients 8 · P99 RT: 106.855 msConcurrent Clients 16 · P99 RT: 212.688 msConcurrent Clients 32 · P99 RT: 693.271 msConcurrent Clients 64 · P99 RT: 1780.555 msRequests/sProcessing Time (ms)Concurrent ClientsRequests/sMedian RTP95 RTP99 RT