| |
@@ -1,11 +1,10 @@
|
| |
import os
|
| |
import flask
|
| |
+ from sqlalchemy.orm import joinedload
|
| |
|
| |
from werkzeug.datastructures import MultiDict
|
| |
from werkzeug.utils import secure_filename
|
| |
|
| |
- from . import get_copr, file_upload, query_params, pagination, Paginator, json2form, GET, POST, PUT, DELETE
|
| |
- from .json2form import get_form_compatible_data
|
| |
from copr_common.enums import StatusEnum
|
| |
from coprs import db, forms, models
|
| |
from coprs.exceptions import (BadRequest, AccessRestricted)
|
| |
@@ -14,6 +13,20 @@
|
| |
from coprs.logic.complex_logic import ComplexLogic
|
| |
from coprs.logic.builds_logic import BuildsLogic
|
| |
|
| |
+ from . import (
|
| |
+ get_copr,
|
| |
+ file_upload,
|
| |
+ query_params,
|
| |
+ pagination,
|
| |
+ SubqueryPaginator,
|
| |
+ json2form,
|
| |
+ GET,
|
| |
+ POST,
|
| |
+ PUT,
|
| |
+ DELETE,
|
| |
+ )
|
| |
+ from .json2form import get_form_compatible_data
|
| |
+
|
| |
|
| |
def to_dict(build):
|
| |
return {
|
| |
@@ -80,9 +93,6 @@
|
| |
@query_params()
|
| |
def get_build_list(ownername, projectname, packagename=None, status=None, **kwargs):
|
| |
copr = get_copr(ownername, projectname)
|
| |
- query = BuildsLogic.get_multiple_by_copr(copr)
|
| |
- if packagename:
|
| |
- query = BuildsLogic.filter_by_package_name(query, packagename)
|
| |
|
| |
# WORKAROUND
|
| |
# We can't filter builds by status directly in the database, because we
|
| |
@@ -93,7 +103,22 @@
|
| |
paginator_limit = None if status else kwargs["limit"]
|
| |
del kwargs["limit"]
|
| |
|
| |
- paginator = Paginator(query, models.Build, limit=paginator_limit, **kwargs)
|
| |
+ # Loading relationships straight away makes running `to_dict` somewhat
|
| |
+ # faster, which adds up over time, and brings a significant speedup for
|
| |
+ # large projects
|
| |
+ query = BuildsLogic.get_multiple()
|
| |
+ query = query.options(
|
| |
+ joinedload(models.Build.build_chroots),
|
| |
+ joinedload(models.Build.package),
|
| |
+ joinedload(models.Build.copr),
|
| |
+ )
|
| |
+
|
| |
+ paginator = SubqueryPaginator(query, models.Build, limit=paginator_limit, **kwargs)
|
| |
+ paginator.subquery = paginator.subquery.filter(models.Build.copr == copr)
|
| |
+ if packagename:
|
| |
+ paginator.subquery = BuildsLogic.filter_by_package_name(
|
| |
+ paginator.subquery, packagename)
|
| |
+
|
| |
builds = paginator.map(to_dict)
|
| |
|
| |
if status:
|
| |
See PR#1914
I found two bottlenecks
1)
to_dict
function isn't extremely slow but it can be made fasterby pre-loading the
models.Build
relationships. This adds up andbrings a significant speedup for large projects
2) Querying the first pages is blazing fast but it gets 10 times
slower when approaching large offsets. We can mitigate the slowdown
at least a little by offseting and limiting within a subquery. It
is also very helpful to query more results per page because the
time for convering database results to JSON remains the same but we
simply don't have to calculate the offset so often.
With this changes, I was able to reduce the time for completing
from 42min to 13min.