swift-kafka-client icon indicating copy to clipboard operation
swift-kafka-client copied to clipboard

Consumer performance benchmark

Open blindspotbounty opened this issue 2 years ago • 5 comments

This PR addresses the need of performance measurements for #132

Motivation

Reading messages with swift-kafka-client KafkaConsumer is up to 50x slower than librdkafka allows.

The following results with 500000 messages in docker (reproducible for 5.7-5.10 compilers):

SwiftKafkaConsumer
╒══════════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                           │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞══════════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ (Alloc + Retain) - Release Δ (K) │    1018 │    1018 │    1018 │    1018 │    1018 │    1018 │    1018 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Memory (allocated) (M)           │     158 │     158 │     158 │     158 │     158 │     158 │     158 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Object allocs (K)                │    2023 │    2023 │    2023 │    2023 │    2023 │    2023 │    2023 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Releases (M)                     │      16 │      16 │      16 │      16 │      16 │      16 │      16 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Retains (M)                      │      13 │      13 │      13 │      13 │      13 │      13 │      13 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)            │    7940 │    7940 │    7940 │    7940 │    7940 │    7940 │    7940 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (s)            │      10 │      10 │      10 │      10 │      10 │      10 │      10 │       1 │
╘══════════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

librdkafka
╒══════════════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                           │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞══════════════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ (Alloc + Retain) - Release Δ     │     101 │     101 │     101 │     101 │     101 │     101 │     101 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Memory (allocated) (M)           │     374 │     374 │     374 │     374 │     374 │     374 │     374 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Object allocs                    │     202 │     202 │     202 │     202 │     202 │     202 │     202 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Releases                         │     303 │     303 │     303 │     303 │     303 │     303 │     303 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Retains                          │       0 │       0 │       0 │       0 │       0 │       0 │       0 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)            │     140 │     140 │     140 │     140 │     140 │     140 │     140 │       1 │
├──────────────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (ms)           │     175 │     175 │     175 │     175 │     175 │     175 │     175 │       1 │
╘══════════════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

Test shows the difference between time 140ms for librdkafka and 7940 for swift-kafka-client, about 57x difference for this run.

Benchmark is added in the same fashion as for https://github.com/apple/swift-nio/pull/2536 and https://github.com/apple/swift-certificates/pull/125.

There are 2 benchmarks:

  1. Benchmark with a simple kafka consumer that fetches 500k messages
  2. Benchmark with a simple librdkafka consumer that fetches 500k messages

All benchmarks can be executed one of the following ways:

  1. Within docker container:
docker-compose -f docker/docker-compose.yaml run benchmark
  1. Locally with kafka running:
swift package --disable-sandbox benchmark  

Additionally tests allow to tweak number of messages, kafka host/port with environment variables with the following defaults:

MESSAGES_NUMBER=500000 
KAFKA_HOST=localhost
KAFKA_PORT=9092 

I have some doubts about committing thresholds as it probably should be done with some CI machine rather than mine.

blindspotbounty avatar Oct 12 '23 16:10 blindspotbounty

I would also review which metrics we'd like for threshold checks.

hassila avatar Oct 13 '23 10:10 hassila

I would also review which metrics we'd like for threshold checks.

I've remained only memory, cpu and wall clock time. That should be enough for the beginning.

blindspotbounty avatar Oct 20 '23 09:10 blindspotbounty

While it is not decided where to put testing utils yet, I've added tests for producer and for producer/consumer with headers. For local run with redpanda (C++ kafka implementation), there are following numbers:

============================
SwiftKafkaConsumerBenchmarks
============================

SwiftKafkaConsumer
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     208 │     208 │     208 │     208 │     208 │     208 │     208 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │    5182 │    5182 │    5182 │    5182 │    5182 │    5182 │    5182 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (s)  │      11 │      11 │      11 │      11 │      11 │      11 │      11 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

SwiftKafkaConsumer with headers
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     179 │     179 │     179 │     179 │     179 │     179 │     179 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │    6850 │    6850 │    6850 │    6850 │    6850 │    6850 │    6850 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (s)  │      13 │      13 │      13 │      13 │      13 │      13 │      13 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

librdkafka consumer
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     290 │     290 │     290 │     290 │     290 │     290 │     290 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │     189 │     189 │     189 │     189 │     189 │     189 │     189 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (ms) │     275 │     275 │     275 │     275 │     275 │     275 │     275 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

librdkafka consumer with headers
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     423 │     423 │     423 │     423 │     423 │     423 │     423 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │     463 │     463 │     463 │     463 │     463 │     463 │     463 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (ms) │     561 │     561 │     561 │     561 │     561 │     561 │     561 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

============================
SwiftKafkaProducerBenchmarks
============================

SwiftKafkaProducer
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     297 │     297 │     297 │     297 │     297 │     297 │     297 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │     647 │     647 │     647 │     647 │     647 │     647 │     647 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (ms) │     832 │     832 │     832 │     832 │     832 │     832 │     832 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

SwiftKafkaProducer with headers
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     442 │     442 │     442 │     442 │     442 │     442 │     442 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │    1875 │    1875 │    1875 │    1875 │    1875 │    1875 │    1875 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (ms) │    2158 │    2158 │    2158 │    2158 │    2158 │    2158 │    2158 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

librdkafka producer
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     177 │     177 │     177 │     177 │     177 │     177 │     177 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │     387 │     387 │     387 │     387 │     387 │     387 │     387 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (ms) │    1186 │    1186 │    1186 │    1186 │    1186 │    1186 │    1186 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

librdkafka producer with headers
╒════════════════════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╤═════════╕
│ Metric                 │      p0 │     p25 │     p50 │     p75 │     p90 │     p99 │    p100 │ Samples │
╞════════════════════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╪═════════╡
│ Memory (allocated) (M) │     272 │     272 │     272 │     272 │     272 │     272 │     272 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (total CPU) (ms)  │    1394 │    1394 │    1394 │    1394 │    1394 │    1394 │    1394 │       1 │
├────────────────────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤
│ Time (wall clock) (ms) │    2019 │    2019 │    2019 │    2019 │    2019 │    2019 │    2019 │       1 │
╘════════════════════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╧═════════╛

blindspotbounty avatar Oct 27 '23 13:10 blindspotbounty

As discussed, opened a PR with infrastructure without actual tests: https://github.com/swift-server/swift-kafka-client/pull/146

blindspotbounty avatar Nov 16 '23 10:11 blindspotbounty

Moving to draft since this PR is going to be closed in favour of others.

PRs containing changes: https://github.com/swift-server/swift-kafka-client/pull/146 https://github.com/swift-server/swift-kafka-client/pull/149

This one is going to be closed after all changes are merged

blindspotbounty avatar Dec 04 '23 15:12 blindspotbounty