Skip to content

Commit

Permalink
benchmark (#103)
Browse files Browse the repository at this point in the history
  • Loading branch information
3nids authored Oct 19, 2023
1 parent 18ed342 commit e7c5320
Show file tree
Hide file tree
Showing 20 changed files with 765 additions and 149 deletions.
80 changes: 80 additions & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Benchmark

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

on:
workflow_dispatch:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
benchmark:
runs-on: ubuntu-latest
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1

steps:
- uses: actions/checkout@v4

- name: Create env
run: cp .env.example .env

- name: Load .env file
uses: xom9ikk/dotenv@v2

- uses: actions/setup-python@v4
with:
python-version: '3.10'
cache: 'pip'

- name: Install deps
run: |
sudo apt-get install -y jq
pip install plotly kaleido
# hyperfine for timing
HF_VERSION=1.18.0
wget https://github.com/sharkdp/hyperfine/releases/download/v${HF_VERSION}/hyperfine_${HF_VERSION}_amd64.deb
sudo dpkg -i hyperfine_${HF_VERSION}_amd64.deb
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build Django image
uses: docker/build-push-action@v5
with:
context: .
provenance: false
file: docker/django/Dockerfile
pull: true
cache-from: type=registry,ref=opengisch/django-oapif:latest
tags: opengisch/django-oapif:latest

- name: Download fixtures
run: ./scripts/download-fixtures.sh

- name: Start Django
run: ./scripts/restart.sh

- name: Run Benchmark
run: ./tests/benchmark/time.sh

- name: Create plots
run: ./tests/benchmark/plot.py

- uses: actions/upload-artifact@v3
with:
path: |
tests/benchmark/results/benchmark.dat
tests/benchmark/results/*.png
if-no-files-found: error

- name: Failure logs
if: failure()
run: docker-compose logs
9 changes: 7 additions & 2 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ jobs:
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
OGCAPIF_HOST: localhost
permissions:
contents: write
pull-requests: write # to write comment

steps:
- uses: actions/checkout@v4

- name: Create env
run: cp .env.example .env

- name: Load .env file
uses: xom9ikk/dotenv@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

Expand Down Expand Up @@ -58,7 +63,7 @@ jobs:
docker compose exec django python manage.py populate_data
- name: Healthcheck
run: wget --no-check-certificate https://localhost/oapif/collections/tests.point_2056_10fields/items
run: wget http://${OGCAPIF_HOST}:${DJANGO_DEV_PORT}/oapif/collections/tests.point_2056_10fields/items

- name: Run conformance test suite
run: docker compose run conformance_test
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@ jobs:
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
OGCAPIF_HOST: localhost

steps:
- uses: actions/checkout@v4

- name: Create env
run: cp .env.example .env

- name: Load .env file
uses: xom9ikk/dotenv@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

Expand Down Expand Up @@ -53,8 +58,7 @@ jobs:
# start the stack
docker compose --profile testing_integration up --build -d
# deploy static files and migrate database
docker compose exec django python manage.py collectstatic --no-input
# migrate database
docker compose exec django python manage.py migrate --no-input
docker compose exec django python manage.py populate_users
docker compose exec django python manage.py populate_data
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ dist
*.egg-info
src/django_oapif/__version__.py

tests/benchmark/results

src/tests/fixtures/polygon_2056.json.gz
src/tests/fixtures/polygon_2056_local_geom.json.gz

data
static
media
test_outputs
.vscode/
.python-version
2 changes: 2 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
exclude: ^src/tests/migrations/

repos:
# Fix end of files
- repo: https://github.com/pre-commit/pre-commit-hooks
Expand Down
7 changes: 7 additions & 0 deletions docker-compose.arm64.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

# see https://github.com/postgis/docker-postgis/issues/216#issuecomment-1763399631
# https://github.com/postgis/docker-postgis/pull/356

services:
postgres:
image: imresamu/postgis-arm64:15-3.4-alpine
2 changes: 1 addition & 1 deletion docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# overrides for local developpement (mounts the source, enables debug, live-reload, etc.)
# overrides for local development (mounts the source, enables debug, live-reload, etc.)
# DO NOT USE ON PRODUCTION !!!

version: '3.7'
Expand Down
2 changes: 1 addition & 1 deletion docker/django/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ RUN apt-get update && \
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# install dev depenencies
# install dev dependencies
ARG DEV=false
COPY ./requirements-dev.txt .
RUN if [ "$DEV" = "true" ] ; then pip install -r requirements-dev.txt ; fi
Expand Down
9 changes: 9 additions & 0 deletions scripts/download-fixtures.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

set -e

mkdir -p src/tests/fixtures

# download fixtures
curl -L -o ./src/tests/fixtures/polygon_2056.json.gz 'https://drive.google.com/uc?export=download&id=1UuGoK_9Y99jiTvQd4juxu85eVZhvlAvy'
curl -L -o ./src/tests/fixtures/polygon_2056_local_geom.json.gz 'https://drive.google.com/uc?export=download&id=18PGtiptcJiRtLnVq7N64EVQLagse0bu0'
14 changes: 14 additions & 0 deletions scripts/populate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/usr/bin/env bash

set -e
set -x

SIZE=${1:-100}


docker compose exec django python manage.py flush --no-input

docker compose exec django python manage.py populate_users
docker compose exec django python manage.py populate_data -s ${SIZE}

docker compose exec django python manage.py loaddata polygon_2056 polygon_2056_local_geom
8 changes: 0 additions & 8 deletions scripts/restart.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,8 @@ set -e

SIZE=${1:-100}

rm src/tests/migrations/0*.py || true

docker compose down --volumes || true

docker compose up --build --force-recreate -d
sleep 5

docker compose exec django python manage.py makemigrations
docker compose exec django python manage.py migrate

docker compose exec django python manage.py collectstatic --no-input
docker compose exec django python manage.py populate_users
docker compose exec django python manage.py populate_data -s ${SIZE}
6 changes: 3 additions & 3 deletions src/django_oapif/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ def inner(Model):
if serialize_geom_in_db and geom_field:

class AutoSerializer(GeoFeatureModelSerializer):
_geom_geosjon = serializers.JSONField(required=False, allow_null=True, read_only=True)
_geom_geojson = serializers.JSONField(required=False, allow_null=True, read_only=True)

class Meta:
model = Model
exclude = [geom_field]
geo_field = "_geom_geosjon"
geo_field = "_geom_geojson"

def to_internal_value(self, data):
# TODO: this needs improvement!!!
Expand Down Expand Up @@ -127,7 +127,7 @@ def get_queryset(self):
qs = super().get_queryset()

if serialize_geom_in_db and geom_field:
qs = qs.annotate(_geom_geosjon=Cast(AsGeoJSON(geom_field, False, False), models.JSONField()))
qs = qs.annotate(_geom_geojson=Cast(AsGeoJSON(geom_field, False, False), models.JSONField()))

return qs

Expand Down
51 changes: 38 additions & 13 deletions src/tests/management/commands/populate_data.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
import math
import random
import string
from copy import deepcopy

from django.core.management import call_command
from django.core.management.base import BaseCommand
from django.db import transaction

from tests.models import (
Line_2056_10fields,
Line_2056_10fields_local_geom,
NoGeom_10fields,
NoGeom_100fields,
Point_2056_10fields,
Point_2056_10fields_local_json,
Point_2056_10fields_local_geom,
SecretLayer,
)


class Command(BaseCommand):
help = "Populate db with testdata"

def add_arguments(self, parser):
parser.add_argument("-s", "--size", type=int, default=10000)
parser.add_argument("-s", "--size", type=int, default=1000)

@transaction.atomic
def handle(self, *args, **options):
Expand All @@ -31,9 +35,12 @@ def handle(self, *args, **options):
magnitude = math.ceil(math.sqrt(size))

points = []
points_local_json = []
points_local_geom = []
secret_points = []
lines = []
lines_local_geom = []
no_geoms = []
no_geoms_100fields = []

letters = string.ascii_lowercase

Expand All @@ -42,30 +49,48 @@ def handle(self, *args, **options):
x = x_start + dx * step
y = y_start + dy * step
geom_pt_wkt = f"Point({x:4f} {y:4f})"
geom_line_wkt = f"LineString({x:4f} {y:4f}, {x+random.randint(10,50):4f} {y+random.randint(10,50):4f})"

fields = {}
geom_line_wkt = (
f"LineString("
f"{x:4f} {y:4f}, "
f"{x+random.randint(10,50):4f} {y+random.randint(10,50):4f})"
f"{x+random.randint(10,50):4f} {y+random.randint(10,50):4f})"
)

fields = {"field_int": random.randint(1, 999)}
for f in range(10):
fields[f"field_{f}"] = "".join(random.choice(letters) for i in range(10))
fields[f"field_str_{f}"] = "".join(random.choice(letters) for i in range(10))

no_geom = NoGeom_10fields(**fields)
no_geoms.append(no_geom)

no_geom_100fields = deepcopy(fields)
for f in range(90):
no_geom_100fields[f"field_str_{10+f}"] = "".join(random.choice(letters) for i in range(10))
no_geom_100fields = NoGeom_100fields(**no_geom_100fields)
no_geoms_100fields.append(no_geom_100fields)

fields["geom"] = geom_pt_wkt
point = Point_2056_10fields(**fields)
points.append(point)
point_local_json = Point_2056_10fields_local_json(**fields)
points_local_json.append(point_local_json)
point_local_geom = Point_2056_10fields_local_geom(**fields)
points_local_geom.append(point_local_geom)
secret_point = SecretLayer(**fields)
secret_points.append(secret_point)

fields["geom"] = geom_line_wkt
line = Line_2056_10fields(**fields)
lines.append(line)
line_local_geom = Line_2056_10fields_local_geom(**fields)
lines_local_geom.append(line_local_geom)

# Create objects in batches
Point_2056_10fields.objects.bulk_create(points)
Point_2056_10fields_local_json.objects.bulk_create(points_local_json)
NoGeom_10fields.objects.bulk_create(no_geoms)
Line_2056_10fields.objects.bulk_create(lines)
Point_2056_10fields.objects.bulk_create(points, batch_size=10000)
Point_2056_10fields_local_geom.objects.bulk_create(points_local_geom, batch_size=10000)
SecretLayer.objects.bulk_create(secret_points, batch_size=10000)
NoGeom_10fields.objects.bulk_create(no_geoms, batch_size=10000)
NoGeom_100fields.objects.bulk_create(no_geoms_100fields, batch_size=10000)
Line_2056_10fields.objects.bulk_create(lines, batch_size=10000)
Line_2056_10fields_local_geom.objects.bulk_create(lines_local_geom, batch_size=10000)

# Call 'update_data' to update computed properties
call_command("updatedata")
Expand Down
Loading

0 comments on commit e7c5320

Please sign in to comment.