mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
benchmarks: Add Accept-Encoding: gzip
headers (NO REGRESSION)
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5622 GitOrigin-RevId: 431f7f382573737af9b85966a58c5b262f8cb377
This commit is contained in:
parent
8fdd0ac8f5
commit
746cae5f4b
@ -83,6 +83,11 @@ be ignored.
|
||||
https://well-typed.com/blog/2021/01/fragmentation-deeper-look/
|
||||
https://well-typed.com/blog/2021/03/memory-return/
|
||||
|
||||
- If optimizing or tuning the output/compression codepath:
|
||||
- `chinook`.`*_small_result` and `simple_query_*` queries are average wrt
|
||||
response body size (according to cloud data)
|
||||
- ...and `chinook`.`full_introspection` is ~P95
|
||||
|
||||
## Adding a new benchmark and reviewing
|
||||
|
||||
You'll create a new directory under `benchmark_sets/`, and in general can
|
||||
|
@ -5,6 +5,11 @@ headers:
|
||||
X-Hasura-Admin-Secret: my-secret
|
||||
X-Hasura-Role: employee
|
||||
X-Hasura-User-Id: 4
|
||||
# On cloud about 95% of requests incoming Accept gzip (which as of writing
|
||||
# means we unconditionally compress, which has significant performance
|
||||
# impact), so it's important that we include it in all benchmarks unless we
|
||||
# have an intentional reason not to.
|
||||
Accept-Encoding: gzip
|
||||
|
||||
# Anchors to help us DRY below; settings here may be overridden selectively
|
||||
constants:
|
||||
@ -36,6 +41,12 @@ queries:
|
||||
############################################################################
|
||||
# single-table query, small result size; makes use of permissions for
|
||||
# filtering; low RPS
|
||||
#
|
||||
# NOTE: According to data from cloud this is a pretty average response (we see
|
||||
# P50 compressed response body size of 123 bytes, and P75 290 bytes):
|
||||
#
|
||||
# uncompressed body size: ~600 bytes
|
||||
# compressed body size: ~200 bytes (as of time of writing)
|
||||
- name: simple_query_low_load
|
||||
<<: *k6_custom
|
||||
options:
|
||||
@ -79,6 +90,10 @@ queries:
|
||||
|
||||
|
||||
######## Small result size
|
||||
#
|
||||
# uncompressed body size: ~650 bytes
|
||||
# compressed body size: ~200 bytes
|
||||
|
||||
- name: complex_query_low_load_small_result
|
||||
<<: *k6_custom
|
||||
options:
|
||||
@ -130,6 +145,13 @@ queries:
|
||||
|
||||
|
||||
######## Large result size
|
||||
#
|
||||
# NOTE: According to data from cloud, this is somewhere between
|
||||
# P90 (2 kB compressed) and P95 (4 kB compressed):
|
||||
#
|
||||
# uncompressed body size: ~33 kB
|
||||
# compressed body size: ~3 kB (as of time of writing)
|
||||
|
||||
- name: complex_query_low_load_large_result
|
||||
<<: *k6_custom
|
||||
options:
|
||||
@ -164,6 +186,12 @@ queries:
|
||||
# The standard introspection query from server/src-rsr/introspection.json
|
||||
# We don't expect a server to be hammered with these, but they are crucial
|
||||
# for clients (like graphiql):
|
||||
#
|
||||
# NOTE: According to data from cloud, this is somewhere between
|
||||
# P95 (4 kB compressed) and P99 (40 kB compressed):
|
||||
#
|
||||
# uncompressed body size: ~190 kB
|
||||
# compressed body size: ~13 kB (as of time of writing)
|
||||
|
||||
- name: full_introspection
|
||||
<<: *k6_custom
|
||||
|
@ -1,8 +1,8 @@
|
||||
# This tells graphql-bench that it's testing a hasura instance and should
|
||||
# collect some additional metrics:
|
||||
extended_hasura_checks: true
|
||||
# headers:
|
||||
# X-Hasura-Admin-Secret: my-secret
|
||||
headers:
|
||||
Accept-Encoding: gzip
|
||||
|
||||
# Anchors to help us DRY below; settings here may be overridden selectively
|
||||
constants:
|
||||
|
@ -1,8 +1,8 @@
|
||||
# This tells graphql-bench that it's testing a hasura instance and should
|
||||
# collect some additional metrics:
|
||||
extended_hasura_checks: true
|
||||
# headers:
|
||||
# X-Hasura-Admin-Secret: my-secret
|
||||
headers:
|
||||
Accept-Encoding: gzip
|
||||
|
||||
# Anchors to help us DRY below; settings here may be overridden selectively
|
||||
constants:
|
||||
|
@ -19,21 +19,26 @@ data CompressionType
|
||||
compressionTypeToTxt :: CompressionType -> Text
|
||||
compressionTypeToTxt CTGZip = "gzip"
|
||||
|
||||
-- | Maybe compress the response body
|
||||
compressResponse ::
|
||||
NH.RequestHeaders ->
|
||||
BL.ByteString ->
|
||||
(BL.ByteString, Maybe NH.Header, Maybe CompressionType)
|
||||
compressResponse reqHeaders unCompressedResp =
|
||||
let compressionTypeM = getRequestedCompression reqHeaders
|
||||
let compressionTypeM = getAcceptedCompression reqHeaders
|
||||
appendCompressionType (res, headerM) = (res, headerM, compressionTypeM)
|
||||
gzipCompressionParams =
|
||||
-- See Note [Compression ratios]
|
||||
GZ.defaultCompressParams {GZ.compressLevel = GZ.compressionLevel 1}
|
||||
in appendCompressionType $ case compressionTypeM of
|
||||
Just CTGZip -> (GZ.compressWith gzipCompressionParams unCompressedResp, Just gzipHeader)
|
||||
Nothing -> (unCompressedResp, Nothing)
|
||||
|
||||
getRequestedCompression :: NH.RequestHeaders -> Maybe CompressionType
|
||||
getRequestedCompression reqHeaders
|
||||
-- | Which, if any, compressed encodings can the client accept?
|
||||
--
|
||||
-- https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
|
||||
getAcceptedCompression :: NH.RequestHeaders -> Maybe CompressionType
|
||||
getAcceptedCompression reqHeaders
|
||||
| "gzip" `elem` acceptEncodingVals = Just CTGZip
|
||||
| otherwise = Nothing
|
||||
where
|
||||
@ -41,3 +46,31 @@ getRequestedCompression reqHeaders
|
||||
concatMap (splitHeaderVal . snd) $
|
||||
filter (\h -> fst h == NH.hAcceptEncoding) reqHeaders
|
||||
splitHeaderVal bs = map T.strip $ T.splitOn "," $ bsToTxt bs
|
||||
|
||||
{-
|
||||
Note [Compression ratios]
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
I did some measurements of compression ratios at `gzip -1` (libc) of some
|
||||
randomly generated json, real json datasets, and output from our benchmarked
|
||||
chinook queries:
|
||||
|
||||
2552/6131 = 0.41
|
||||
4666/8718 = 0.53
|
||||
13921/27131 = 0.51
|
||||
5895/8879 = 0.66 <----- completely random strings
|
||||
8634/28261 = 0.30
|
||||
70422/372466 = 0.18
|
||||
|
||||
200/600 = 0.33 <----| from chinook graphql benchmarks
|
||||
3000/33000 = 0.09 <----|
|
||||
13000/190000 = 0.07 <----'
|
||||
|
||||
Given these numbers I would suggest using a rule-of-thumb expected compression
|
||||
ratio between 2:1 and 10:1, depending on what being conservative means in the
|
||||
context.
|
||||
|
||||
I didn't test higher compression levels much, but `gzip -4` for the most part
|
||||
resulted in less than 10% smaller output on random json, and ~30% on our highly
|
||||
compressible benchmark output.
|
||||
-}
|
||||
|
Loading…
Reference in New Issue
Block a user