nix: add --method for postgrest-loadtest

Currently the `postgrest-loadtest -k jwt-*` loadtests use the OPTIONS method,
which is good for isolating the perf changes for JWT auth.

But using GET is more accurate for actual perf improvements,
since it actually hits the database.

This adds a method argument for postgrest-loadtest, so GET can be used like:

```
postgrest-loadtest -k jwt-hs --method GET
```

CI is not changed, this is mostly useful for manually checking variance.
This commit is contained in:
steve-chavez
2025-12-12 14:46:46 -05:00
committed by Steve Chavez
parent 90bf1762ae
commit 99b8246d6e
2 changed files with 35 additions and 10 deletions
+27 -4
View File
@@ -18,6 +18,7 @@ import jwt
import jwcrypto.jwk as jwk import jwcrypto.jwk as jwk
from typing import Optional from typing import Optional
from pathlib import Path from pathlib import Path
from enum import Enum
URL = "http://postgrest" URL = "http://postgrest"
@@ -44,8 +45,21 @@ def generate_jwt(now: int, exp_inc: Optional[int], is_hs: bool) -> str:
return jwt.encode(payload, k, alg) return jwt.encode(payload, k, alg)
def append_targets(lines: list[str], token: str): HTTP_METHODS = (
lines.append(f"OPTIONS {URL}/authors_only") "GET",
"OPTIONS",
)
HttpMethod = Enum(
"HttpMethod",
{method: method for method in HTTP_METHODS},
type=str,
module=__name__,
)
def append_targets(lines: list[str], token: str, http_method: HttpMethod):
lines.append(f"{http_method.value} {URL}/authors_only")
lines.append(f"Authorization: Bearer {token}") lines.append(f"Authorization: Bearer {token}")
lines.append("") # blank line to separate requests lines.append("") # blank line to separate requests
@@ -73,11 +87,20 @@ def main():
default=None, default=None,
help="Path for generating a RSA JWK file to sign tokens with", help="Path for generating a RSA JWK file to sign tokens with",
) )
parser.add_argument(
"--method",
dest="http_method",
choices=list(HTTP_METHODS),
default=None,
help="HTTP method for the vegeta targets",
)
args = parser.parse_args() args = parser.parse_args()
is_hs = args.jwk_path is None is_hs = args.jwk_path is None
http_method = HttpMethod(args.http_method)
nsamples = 1000 nsamples = 1000
if is_hs: if is_hs:
ntargets = 200000 ntargets = 200000
@@ -122,13 +145,13 @@ def main():
for i in range(ntargets): for i in range(ntargets):
token = generate_jwt(now, inc + i // 1000, is_hs) token = generate_jwt(now, inc + i // 1000, is_hs)
append_targets(lines, token) append_targets(lines, token, http_method)
else: else:
tokens = [generate_jwt(now, None, is_hs) for _ in range(nsamples)] tokens = [generate_jwt(now, None, is_hs) for _ in range(nsamples)]
for i in range(ntargets): for i in range(ntargets):
token = random.choice(tokens) token = random.choice(tokens)
append_targets(lines, token) append_targets(lines, token, http_method)
try: try:
with open(args.output, "w") as f: with open(args.output, "w") as f:
+8 -6
View File
@@ -42,7 +42,9 @@ let
"ARG_OPTIONAL_SINGLE([output], [o], [Filename to dump json output to], [./loadtest/result.bin])" "ARG_OPTIONAL_SINGLE([output], [o], [Filename to dump json output to], [./loadtest/result.bin])"
"ARG_OPTIONAL_SINGLE([testdir], [t], [Directory to load tests and fixtures from], [./test/load])" "ARG_OPTIONAL_SINGLE([testdir], [t], [Directory to load tests and fixtures from], [./test/load])"
"ARG_OPTIONAL_SINGLE([kind], [k], [Kind of loadtest], [mixed])" "ARG_OPTIONAL_SINGLE([kind], [k], [Kind of loadtest], [mixed])"
"ARG_OPTIONAL_SINGLE([method],, [HTTP method used for the jwt loadtests], [OPTIONS])"
"ARG_TYPE_GROUP_SET([KIND], [KIND], [kind], [mixed,jwt-hs,jwt-hs-cache,jwt-hs-cache-worst,jwt-rsa,jwt-rsa-cache,jwt-rsa-cache-worst])" "ARG_TYPE_GROUP_SET([KIND], [KIND], [kind], [mixed,jwt-hs,jwt-hs-cache,jwt-hs-cache-worst,jwt-rsa,jwt-rsa-cache,jwt-rsa-cache-worst])"
"ARG_TYPE_GROUP_SET([METHOD], [METHOD], [method], [OPTIONS,GET])"
"ARG_OPTIONAL_SINGLE([monitor], [m], [Monitoring file], [./loadtest/result.csv])" "ARG_OPTIONAL_SINGLE([monitor], [m], [Monitoring file], [./loadtest/result.csv])"
"ARG_LEFTOVERS([additional vegeta arguments])" "ARG_LEFTOVERS([additional vegeta arguments])"
]; ];
@@ -69,33 +71,33 @@ let
case "$_arg_kind" in case "$_arg_kind" in
jwt-hs) jwt-hs)
${genTargets} "$_arg_testdir"/gen_targets.http ${genTargets} --method "$_arg_method" "$_arg_testdir"/gen_targets.http
export PGRST_JWT_CACHE_MAX_ENTRIES="0" export PGRST_JWT_CACHE_MAX_ENTRIES="0"
export PGRST_JWT_CACHE_MAX_LIFETIME="0" export PGRST_JWT_CACHE_MAX_LIFETIME="0"
;; ;;
jwt-hs-cache) jwt-hs-cache)
${genTargets} "$_arg_testdir"/gen_targets.http ${genTargets} --method "$_arg_method" "$_arg_testdir"/gen_targets.http
;; ;;
jwt-hs-cache-worst) jwt-hs-cache-worst)
${genTargets} --worst "$_arg_testdir"/gen_targets.http ${genTargets} --method "$_arg_method" --worst "$_arg_testdir"/gen_targets.http
;; ;;
jwt-rsa) jwt-rsa)
${genTargets} --rsa="$_arg_testdir"/gen_jwk.json "$_arg_testdir"/gen_targets.http ${genTargets} --method "$_arg_method" --rsa="$_arg_testdir"/gen_jwk.json "$_arg_testdir"/gen_targets.http
export PGRST_JWT_CACHE_MAX_ENTRIES="0" export PGRST_JWT_CACHE_MAX_ENTRIES="0"
export PGRST_JWT_CACHE_MAX_LIFETIME="0" export PGRST_JWT_CACHE_MAX_LIFETIME="0"
export PGRST_JWT_SECRET="@$_arg_testdir/gen_jwk.json" export PGRST_JWT_SECRET="@$_arg_testdir/gen_jwk.json"
;; ;;
jwt-rsa-cache) jwt-rsa-cache)
${genTargets} --rsa="$_arg_testdir"/gen_jwk.json "$_arg_testdir"/gen_targets.http ${genTargets} --method "$_arg_method" --rsa="$_arg_testdir"/gen_jwk.json "$_arg_testdir"/gen_targets.http
export PGRST_JWT_SECRET="@$_arg_testdir/gen_jwk.json" export PGRST_JWT_SECRET="@$_arg_testdir/gen_jwk.json"
;; ;;
jwt-rsa-cache-worst) jwt-rsa-cache-worst)
${genTargets} --worst --rsa="$_arg_testdir"/gen_jwk.json "$_arg_testdir"/gen_targets.http ${genTargets} --method "$_arg_method" --worst --rsa="$_arg_testdir"/gen_jwk.json "$_arg_testdir"/gen_targets.http
export PGRST_JWT_SECRET="@$_arg_testdir/gen_jwk.json" export PGRST_JWT_SECRET="@$_arg_testdir/gen_jwk.json"
;; ;;