swift-server / swift-kafka-client

Apache License 2.0
83 stars 23 forks source link

Consumer performance benchmark #140

Closed blindspotbounty closed 3 weeks ago

blindspotbounty commented 1 year ago

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
  2. 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.

hassila commented 1 year ago

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

blindspotbounty commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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

blindspotbounty commented 11 months ago

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