init benchmarks

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
Marc 'risson' Schmitt
2024-04-05 05:32:40 +02:00
parent 2e0907af1e
commit a7cb808cad
9 changed files with 144 additions and 0 deletions

6
.gitignore vendored
View File

@ -209,3 +209,9 @@ source_docs/
### Golang ###
/vendor/
### Benchmark ###
tests/benchmark/k6
tests/benchmark/**/*.json
tests/benchmark/**/*.ndjson
tests/benchmark/**/*.html

View File

@ -278,3 +278,12 @@ ci-bandit: ci--meta-debug
ci-pending-migrations: ci--meta-debug
ak makemigrations --check
#########################
## Benchmark
#########################
benchmark-install:
cd tests/benchmark
go install go.k6.io/xk6/cmd/xk6@latest
$$(go env GOPATH)/bin/xk6 build latest --with github.com/grafana/xk6-exec@latest

View File

@ -4,6 +4,7 @@ services:
postgresql:
container_name: postgres
image: docker.io/library/postgres:16
command: "-c max_connections=500"
volumes:
- db-data:/var/lib/postgresql/data
environment:

View File

View File

@ -0,0 +1,9 @@
#!/usr/bin/env python3
import sys
from uuid import uuid4
from tests.benchmark.init import *
while User.objects.count() < int(sys.argv[1]):
User.objects.create(username=uuid4(), name=uuid4())

View File

@ -0,0 +1,7 @@
#!/usr/bin/env python3
from uuid import uuid4
from tests.benchmark.init import *
User.objects.exclude_anonymous().exclude(username="akadmin").delete()

8
tests/benchmark/init.py Normal file
View File

@ -0,0 +1,8 @@
from os import environ
import django
environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
django.setup()
from authentik.core.models import User

30
tests/benchmark/run.sh Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -euo pipefail
BASE_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
function _k6 {
local filename="${1}"
"${BASE_DIR}/k6" \
run \
--out "web-dashboard=port=-1&report=${filename%.*}.html&period=1s&tag=name&tag=group&tag=user_count&tag=page_size" \
--out "json=${filename%.*}.json" \
"${@}"
}
filename=""
if [ "${#}" -ge 1 ]; then
filename="${1:-}"
shift
fi
if [ -f "${filename}" ]; then
_k6 "${filename}" "${@}"
else
find "${BASE_DIR}" -name '*.js' | while read -r f; do
_k6 "${f}" "${@}"
done
fi

74
tests/benchmark/user_list.js Executable file
View File

@ -0,0 +1,74 @@
import exec from "k6/execution";
import { command } from "k6/x/exec";
import http from "k6/http";
import { check, group } from "k6";
export const options = {
discardResponseBodies: true,
scenarios: Object.fromEntries(
[
[10, 20],
[100, 20],
[1000, 20],
[10000, 20],
[10, 100],
[100, 100],
[1000, 100],
[10000, 100],
].map((obj, i) => [
`${obj[0]}_${obj[1]}`,
{
executor: "constant-vus",
vus: 10,
duration: "10s",
startTime: `${10 * i}s`,
env: {
USER_COUNT: `${obj[0]}`,
PAGE_SIZE: `${obj[1]}`,
},
tags: {
user_count: `${obj[0]}`,
page_size: `${obj[1]}`,
},
},
]),
),
};
export function setup() {
command("./create_users.py", ["11000"]);
}
export function teardown() {
command("./delete_users.py");
}
export default function () {
const user_count = Number(__ENV.USER_COUNT);
const page_size = Number(__ENV.PAGE_SIZE);
const pages = Math.round(user_count / 20);
let requests = [];
for (let page = 1; page <= pages; page++) {
requests.push([
"GET",
`http://localhost:9000/api/v3/core/users/?page=${page}&page_size=${page_size}`,
null,
{
headers: {
Authorization: "Bearer akadmin",
"Content-Type": "application/json",
Accept: "*/*",
},
tags: {
name: "/core/users/",
},
},
]);
}
const responses = http.batch(requests);
for (let page = 1; page <= pages; page++) {
check(responses[page - 1], {
"status is 200": (res) => res.status === 200,
});
}
}