Skip to content

fix(ktor): gzip level 1 instead of default level 6#136

Open
BennyFranciscus wants to merge 1 commit intoMDA2AV:mainfrom
BennyFranciscus:fix/ktor-gzip-level1
Open

fix(ktor): gzip level 1 instead of default level 6#136
BennyFranciscus wants to merge 1 commit intoMDA2AV:mainfrom
BennyFranciscus:fix/ktor-gzip-level1

Conversation

@BennyFranciscus
Copy link
Copy Markdown
Collaborator

Sets Deflater.BEST_SPEED (level 1) for gzip compression on /compression endpoint, matching the HttpArena test requirement.

The default GZIPOutputStream constructor uses Deflater.DEFAULT_COMPRESSION (level 6). This fix overrides it to level 1 via the def field.

Closes #107

Sets Deflater.BEST_SPEED (level 1) for gzip compression on /compression
endpoint, matching the HttpArena test requirement.

Closes MDA2AV#107
@MDA2AV
Copy link
Copy Markdown
Owner

MDA2AV commented Mar 26, 2026

/benchmark compression

@github-actions
Copy link
Copy Markdown

🚀 Benchmark run triggered for ktor (profile: compression). Results will be posted here when done.

@github-actions
Copy link
Copy Markdown

Benchmark Results

Framework: ktor | Profile: compression

ktor / compression / 4096c (p=1, r=0, cpu=unlimited)
  Best: 10183 req/s (CPU: 12078.5%, Mem: 5.4GiB) ===

ktor / compression / 16384c (p=1, r=0, cpu=unlimited)
  Best: 9876 req/s (CPU: 11312.9%, Mem: 6.1GiB) ===
Full log

#5 [internal] load build context
#5 DONE 0.0s

#6 [build 1/6] FROM docker.io/library/gradle:8.12-jdk21@sha256:4c01ef2d5b57f88578b20891d8640dc799855731b977850940057c1ea37ba8a6
#6 resolve docker.io/library/gradle:8.12-jdk21@sha256:4c01ef2d5b57f88578b20891d8640dc799855731b977850940057c1ea37ba8a6 0.1s done
#6 DONE 0.1s

#7 [stage-1 1/3] FROM docker.io/library/eclipse-temurin:21-jre@sha256:9d4453b48613404e1fa6e5e7eabc687ea57edfb8a1ad413956c5168f84b66af9
#7 resolve docker.io/library/eclipse-temurin:21-jre@sha256:9d4453b48613404e1fa6e5e7eabc687ea57edfb8a1ad413956c5168f84b66af9 0.1s done
#7 DONE 0.1s

#5 [internal] load build context
#5 transferring context: 10.95kB done
#5 DONE 0.0s

#8 [build 2/6] WORKDIR /app
#8 CACHED

#9 [build 4/6] RUN gradle dependencies --no-daemon -q 2>/dev/null || true
#9 CACHED

#10 [build 5/6] COPY src ./src
#10 CACHED

#11 [build 6/6] RUN gradle buildFatJar --no-daemon -q
#11 CACHED

#12 [build 3/6] COPY build.gradle.kts settings.gradle.kts gradle.properties ./
#12 CACHED

#13 [stage-1 2/3] WORKDIR /app
#13 CACHED

#14 [stage-1 3/3] COPY --from=build /app/build/libs/ktor-httparena.jar .
#14 CACHED

#15 exporting to image
#15 exporting layers done
#15 exporting manifest sha256:f2ffd4b1669c467e243f095544b673c8c318be86eb1492dc55cd5cb5f866085c done
#15 exporting config sha256:334d401e1c8f84af70bfeae679e078b0c5460efe5f41aec80f04cd826c060f58 done
#15 exporting attestation manifest sha256:de6c7e9d83299924a0de5fab918022347e7549e2dbf22d52ce6d158aaa0f5912 0.0s done
#15 exporting manifest list sha256:35d524ddea8bf34e4ceb677040f7076b574edb7a263b7f87a0b1c2b1892384ee
#15 exporting manifest list sha256:35d524ddea8bf34e4ceb677040f7076b574edb7a263b7f87a0b1c2b1892384ee 0.0s done
#15 naming to docker.io/library/httparena-ktor:latest done
#15 unpacking to docker.io/library/httparena-ktor:latest 0.0s done
#15 DONE 0.1s

==============================================
=== ktor / compression / 4096c (p=1, r=0, cpu=unlimited) ===
==============================================
89687bf7108577dcc9045a76f4fce95dd0660e7fcad14d00a1db351383f34042
[wait] Waiting for server...
[ready] Server is up

[run 1/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   429.44ms   394.80ms   550.50ms    1.14s    1.32s

  47244 requests in 5.00s, 45560 responses
  Throughput: 9.11K req/s
  Bandwidth:  1.99GB/s
  Status codes: 2xx=45560, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 45560 / 45560 responses (100.0%)
  CPU: 10956.8% | Mem: 5.4GiB

[run 2/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   386.03ms   391.60ms   435.10ms   615.90ms   723.10ms

  50980 requests in 5.00s, 50916 responses
  Throughput: 10.18K req/s
  Bandwidth:  2.23GB/s
  Status codes: 2xx=50916, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 50916 / 50916 responses (100.0%)
  CPU: 12078.5% | Mem: 5.4GiB

[run 3/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   385.21ms   390.10ms   433.00ms   618.20ms   749.70ms

  50866 requests in 5.00s, 50866 responses
  Throughput: 10.17K req/s
  Bandwidth:  2.23GB/s
  Status codes: 2xx=50866, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 50865 / 50866 responses (100.0%)
  CPU: 12000.2% | Mem: 5.4GiB

=== Best: 10183 req/s (CPU: 12078.5%, Mem: 5.4GiB) ===
  Input BW: 735.88KB/s (avg template: 74 bytes)
[dry-run] Results not saved (use --save to persist)
httparena-bench-ktor
httparena-bench-ktor

==============================================
=== ktor / compression / 16384c (p=1, r=0, cpu=unlimited) ===
==============================================
1758a7dbab97b6276e4fb057f3fff152cc68c3dc4e112f61de57ee37707c3629
[wait] Waiting for server...
[ready] Server is up

[run 1/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    1.27s    1.37s    2.24s    3.36s    3.63s

  59573 requests in 5.00s, 43189 responses
  Throughput: 8.63K req/s
  Bandwidth:  1.89GB/s
  Status codes: 2xx=43189, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 43189 / 43189 responses (100.0%)
  CPU: 10641.7% | Mem: 6.0GiB

[run 2/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    1.19s    1.36s    1.73s    1.96s    2.45s

  65585 requests in 5.00s, 49201 responses
  Throughput: 9.84K req/s
  Bandwidth:  2.15GB/s
  Status codes: 2xx=49201, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 49201 / 49201 responses (100.0%)
  CPU: 11884.6% | Mem: 6.1GiB

[run 3/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    1.18s    1.34s    1.70s    2.00s    2.14s

  65768 requests in 5.00s, 49384 responses
  Throughput: 9.87K req/s
  Bandwidth:  2.16GB/s
  Status codes: 2xx=49384, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 49384 / 49384 responses (100.0%)
  CPU: 11312.9% | Mem: 6.1GiB

=== Best: 9876 req/s (CPU: 11312.9%, Mem: 6.1GiB) ===
  Input BW: 713.70KB/s (avg template: 74 bytes)
[dry-run] Results not saved (use --save to persist)
httparena-bench-ktor
httparena-bench-ktor
[restore] Restoring CPU governor to powersave...

@BennyFranciscus
Copy link
Copy Markdown
Collaborator Author

Nice, ~10.1K req/s at 4096c with level 1 compression. That's a solid result for Ktor — Java's GZIPOutputStream isn't the fastest gzip impl out there but level 1 makes a big difference vs the default level 6.

Latency looks reasonable too, p99 around 600-620ms under load. The 16384c numbers dipping slightly to ~9.9K makes sense — more connections = more scheduling overhead on the JVM side.

Should be good to merge I think, this brings Ktor in line with what the other frameworks are doing for the compression profile.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Audit] ktor: gzip compression uses default level 6 instead of required level 1

2 participants