Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

not prefetching images when not needed #8676

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### Fixed

- Optimized memory consumption when importing annotations to a task with a lot of jobs and images
(<https://github.com/cvat-ai/cvat/pull/8676>)
24 changes: 14 additions & 10 deletions cvat/apps/dataset_manager/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from datumaro.components.errors import DatasetError, DatasetImportError, DatasetNotFoundError

from django.db import transaction
from django.db.models.query import Prefetch
from django.db.models.query import Prefetch, QuerySet
from django.conf import settings
from rest_framework.exceptions import ValidationError

Expand Down Expand Up @@ -81,9 +81,10 @@ def merge_table_rows(rows, keys_for_merge, field_id):

return list(merged_rows.values())


class JobAnnotation:
@classmethod
def add_prefetch_info(cls, queryset):
def add_prefetch_info(cls, queryset: QuerySet, prefetch_images: bool = True):
assert issubclass(queryset.model, models.Job)

label_qs = add_prefetch_fields(models.Label.objects.all(), [
Expand All @@ -93,6 +94,12 @@ def add_prefetch_info(cls, queryset):
])
label_qs = JobData.add_prefetch_info(label_qs)

task_data_queryset = models.Data.objects.select_related('video')
if prefetch_images:
task_data_queryset = task_data_queryset.prefetch_related(
Prefetch('images', queryset=models.Image.objects.order_by('frame'))
)

return queryset.select_related(
'segment',
'segment__task',
Expand All @@ -103,18 +110,15 @@ def add_prefetch_info(cls, queryset):
'segment__task__project__owner',
'segment__task__project__assignee',

Prefetch('segment__task__data',
queryset=models.Data.objects.select_related('video').prefetch_related(
Prefetch('images', queryset=models.Image.objects.order_by('frame'))
)),
Prefetch('segment__task__data', queryset=task_data_queryset),

Prefetch('segment__task__label_set', queryset=label_qs),
Prefetch('segment__task__project__label_set', queryset=label_qs),
)

def __init__(self, pk, *, is_prefetched=False, queryset=None):
def __init__(self, pk, *, is_prefetched: bool = False, queryset: QuerySet = None, prefetch_images: bool = True):
if queryset is None:
queryset = self.add_prefetch_info(models.Job.objects)
queryset = self.add_prefetch_info(models.Job.objects, prefetch_images=prefetch_images)

if is_prefetched:
self.db_job: models.Job = queryset.select_related(
Expand Down Expand Up @@ -1018,7 +1022,7 @@ def put_job_data(pk, data):
@plugin_decorator
@transaction.atomic
def patch_job_data(pk, data, action):
annotation = JobAnnotation(pk)
annotation = JobAnnotation(pk, prefetch_images=False)
if action == PatchAction.CREATE:
annotation.create(data)
elif action == PatchAction.UPDATE:
Expand All @@ -1031,7 +1035,7 @@ def patch_job_data(pk, data, action):
@silk_profile(name="DELETE job data")
@transaction.atomic
def delete_job_data(pk):
annotation = JobAnnotation(pk)
annotation = JobAnnotation(pk, prefetch_images=False)
annotation.delete()

def export_job(job_id, dst_file, format_name, server_url=None, save_images=False):
Expand Down
Loading