mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-08-01 08:32:18 +00:00
Adds standalone profiling tooling (never merged into dev/main): a persistent, self-healing Postgres 18 container helper (run_with_postgres.sh/stop_postgres.sh), a scale-profile dataset seeder (seed.py) whose document counts and guardian permission-row ratios mirror real bug reports (#13276, #13161), and a typed profiling harness (harness.py) for timing/query-count comparisons and EXPLAIN ANALYZE capture, gated by require_postgres() so it never silently runs on SQLite. seed.py samples distinct (subject, document) pairs up front rather than drawing with replacement, since guardian's assign_perm() dedupes on the (subject, object, permission) triple -- with-replacement sampling against a small group pool collides heavily (birthday paradox) and undercounts the target permission-row ratios otherwise.
47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
# profiling/test_harness_self_check.py
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from profiling.harness import require_postgres
|
|
from profiling.harness import run_profile
|
|
from profiling.seed import seed_permission_dataset
|
|
|
|
|
|
@pytest.mark.profiling
|
|
@pytest.mark.django_db
|
|
def test_seed_medium_scale_produces_expected_counts() -> None:
|
|
require_postgres()
|
|
data = seed_permission_dataset(scale="medium")
|
|
assert len(data.documents) == 20_000
|
|
assert len(data.tags) == 100
|
|
assert len(data.correspondents) == 300
|
|
assert len(data.document_types) == 50
|
|
assert len(data.storage_paths) == 20
|
|
|
|
from guardian.models import GroupObjectPermission
|
|
from guardian.models import UserObjectPermission
|
|
|
|
user_perm_count = UserObjectPermission.objects.count()
|
|
group_perm_count = GroupObjectPermission.objects.count()
|
|
# within 5% of the ratio-derived target -- exact counts depend on random
|
|
# sampling without replacement, see seed.py
|
|
assert 2_242 <= user_perm_count <= 2_478
|
|
assert 43_111 <= group_perm_count <= 47_649
|
|
|
|
|
|
@pytest.mark.profiling
|
|
@pytest.mark.django_db
|
|
def test_run_profile_reports_query_count_and_timing() -> None:
|
|
require_postgres()
|
|
|
|
def trivial() -> list[int]:
|
|
from documents.models import Document
|
|
|
|
return list(Document.objects.values_list("id", flat=True)[:1])
|
|
|
|
result = run_profile(trivial, repeat=3)
|
|
assert result.best_seconds >= 0
|
|
assert len(result.all_seconds) == 3
|
|
assert result.query_count >= 1
|