Skip to content

Commit ad08cd9

Browse files
Vaghinak BasentsyanVaghinak Basentsyan
authored andcommitted
Performance fix
1 parent 4e4375f commit ad08cd9

File tree

6 files changed

+70
-43
lines changed

6 files changed

+70
-43
lines changed

src/superannotate/lib/app/interface/sdk_interface.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,7 @@ def upload_images_from_folder_to_project(
15561556
)
15571557
images_to_upload, _ = use_case.images_to_upload
15581558
if use_case.is_valid():
1559-
with tqdm(total=len(images_to_upload)) as progress_bar:
1559+
with tqdm(total=len(images_to_upload), desc="Uploading images") as progress_bar:
15601560
for _ in use_case.execute():
15611561
progress_bar.update(1)
15621562
return use_case.data
@@ -1859,7 +1859,7 @@ def upload_videos_from_folder_to_project(
18591859
)
18601860

18611861
uploaded_images, failed_images = [], []
1862-
for path in tqdm(video_paths):
1862+
for path in tqdm(video_paths, desc="Uploading videos"):
18631863
with tempfile.TemporaryDirectory() as temp_path:
18641864
res = controller.extract_video_frames(
18651865
project_name=project_name,
@@ -1953,7 +1953,9 @@ def upload_video_to_project(
19531953
)
19541954
images_to_upload, _ = use_case.images_to_upload
19551955
if use_case.is_valid():
1956-
with tqdm(total=len(images_to_upload)) as progress_bar:
1956+
with tqdm(
1957+
total=len(images_to_upload), desc="Uploading frames."
1958+
) as progress_bar:
19571959
for _ in use_case.execute():
19581960
progress_bar.update(1)
19591961
return use_case.data[0]
@@ -2488,8 +2490,10 @@ def upload_annotations_from_folder_to_project(
24882490
uploaded_annotations = []
24892491
failed_annotations = []
24902492
missing_annotations = []
2491-
chunk_size = 10
2492-
with tqdm(total=len(annotation_paths)) as progress_bar:
2493+
chunk_size = 50
2494+
with tqdm(
2495+
total=len(annotation_paths), desc="Uploading annotations"
2496+
) as progress_bar:
24932497
for i in range(0, len(annotation_paths), chunk_size):
24942498
response = controller.upload_annotations_from_folder(
24952499
project_name=project_name,
@@ -2549,7 +2553,9 @@ def upload_preannotations_from_folder_to_project(
25492553
failed_annotations = []
25502554
missing_annotations = []
25512555
chunk_size = 10
2552-
with tqdm(total=len(annotation_paths)) as progress_bar:
2556+
with tqdm(
2557+
total=len(annotation_paths), desc="Uploading pre annotations"
2558+
) as progress_bar:
25532559
for i in range(0, len(annotation_paths), chunk_size):
25542560
response = controller.upload_annotations_from_folder(
25552561
project_name=project_name,
@@ -3511,7 +3517,7 @@ def _upload_s3_image(image_path: str):
35113517
executor.submit(upload_method, image_path)
35123518
for image_path in images_to_upload
35133519
]
3514-
with tqdm(total=len(images_to_upload)) as progress_bar:
3520+
with tqdm(total=len(images_to_upload), desc="Uploading images") as progress_bar:
35153521
for future in concurrent.futures.as_completed(results):
35163522
processed_image = future.result()
35173523
if processed_image.uploaded and processed_image.entity:

src/superannotate/lib/core/usecases.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ class UploadImageS3UseCase(BaseUseCase):
504504
def __init__(
505505
self,
506506
project: ProjectEntity,
507-
project_settings: BaseReadOnlyRepository,
507+
project_settings: List[ProjectSettingEntity],
508508
image_path: str,
509509
image: io.BytesIO,
510510
s3_repo: BaseManageableRepository,
@@ -535,7 +535,7 @@ def execute(self):
535535
huge_image, huge_width, huge_height = image_processor.generate_huge()
536536
quality = 60
537537
if not self._image_quality_in_editor:
538-
for setting in self._project_settings.get_all():
538+
for setting in self._project_settings:
539539
if setting.attribute == "ImageQuality":
540540
quality = setting.value
541541
else:
@@ -679,7 +679,11 @@ def execute(self):
679679
folder_id=self._folder.uuid,
680680
images=[image.name for image in self._attachments],
681681
)
682-
duplications = [image["name"] for image in duplications]
682+
try:
683+
duplications = [image["name"] for image in duplications]
684+
except Exception:
685+
print(duplications)
686+
raise
683687
meta = {}
684688
to_upload = []
685689
for image in self._attachments:
@@ -1062,7 +1066,7 @@ def execute(self):
10621066
headers=annotations["annotation_json_path"]["headers"],
10631067
)
10641068
if not response.ok:
1065-
raise AppException(f"Couldn't load annotations.")
1069+
raise AppException("Couldn't load annotations.")
10661070

10671071
image_annotations = response.json()
10681072
from_project_annotation_classes = (
@@ -1153,7 +1157,7 @@ def execute(self):
11531157
headers=annotations["annotation_bluemap_path"]["headers"],
11541158
)
11551159
if not response.ok:
1156-
raise AppException(f"Couldn't load annotations.")
1160+
raise AppException("Couldn't load annotations.")
11571161
self.to_project_s3_repo.insert(
11581162
S3FileEntity(
11591163
auth_data["annotation_bluemap_path"]["filePath"], response.content
@@ -2082,7 +2086,7 @@ def execute(self):
20822086
headers=credentials["annotation_json_path"]["headers"],
20832087
)
20842088
if not response.ok:
2085-
logger.warning(f"Couldn't load annotations.")
2089+
logger.warning("Couldn't load annotations.")
20862090
self._response.data = data
20872091
return self._response
20882092
data["annotation_json"] = response.json()
@@ -2177,7 +2181,7 @@ def execute(self):
21772181
url=annotation_json_creds["url"], headers=annotation_json_creds["headers"],
21782182
)
21792183
if not response.ok:
2180-
raise AppException(f"Couldn't load annotations.")
2184+
raise AppException("Couldn't load annotations.")
21812185
data["preannotation_json"] = response.json()
21822186
data["preannotation_json_filename"] = f"{self._image_name}{file_postfix}"
21832187
if self._project.project_type == constances.ProjectType.PIXEL.value:
@@ -2254,7 +2258,7 @@ def execute(self):
22542258
headers=annotation_json_creds["headers"],
22552259
)
22562260
if not response.ok:
2257-
logger.warning(f"Couldn't load annotations.")
2261+
logger.warning("Couldn't load annotations.")
22582262
self._response.data = (None, None)
22592263
return self._response
22602264
data["annotation_json"] = response.json()
@@ -2333,7 +2337,7 @@ def execute(self):
23332337
url=annotation_json_creds["url"], headers=annotation_json_creds["headers"],
23342338
)
23352339
if not response.ok:
2336-
raise AppException(f"Couldn't load annotations.")
2340+
raise AppException("Couldn't load annotations.")
23372341
data["preannotation_json"] = response.json()
23382342
data["preannotation_json_filename"] = f"{self._image_name}{file_postfix}"
23392343
mask_path = None
@@ -3272,10 +3276,11 @@ def __init__(
32723276
self,
32733277
project: ProjectEntity,
32743278
folder: FolderEntity,
3275-
annotation_classes: BaseReadOnlyRepository,
3279+
annotation_classes: List[AnnotationClassEntity],
32763280
folder_path: str,
32773281
annotation_paths: List[str],
32783282
backend_service_provider: SuerannotateServiceProvider,
3283+
templates: List[dict],
32793284
pre_annotation: bool = False,
32803285
client_s3_bucket=None,
32813286
):
@@ -3288,6 +3293,7 @@ def __init__(
32883293
self._annotation_paths = annotation_paths
32893294
self._client_s3_bucket = client_s3_bucket
32903295
self._pre_annotation = pre_annotation
3296+
self._templates = templates
32913297

32923298
@property
32933299
def s3_client(self):
@@ -3296,7 +3302,7 @@ def s3_client(self):
32963302
@property
32973303
def annotation_classes_name_map(self) -> dict:
32983304
classes_data = defaultdict(dict)
3299-
annotation_classes = self._annotation_classes.get_all()
3305+
annotation_classes = self._annotation_classes
33003306
for annotation_class in annotation_classes:
33013307
class_info = {"id": annotation_class.uuid}
33023308
if annotation_class.attribute_groups:
@@ -3322,11 +3328,8 @@ def annotation_postfix(self):
33223328
)
33233329

33243330
def get_templates_mapping(self):
3325-
templates = self._backend_service.get_templates(
3326-
team_id=self._project.team_id
3327-
).get("data", [])
33283331
templates_map = {}
3329-
for template in templates:
3332+
for template in self._templates:
33303333
templates_map[template["name"]] = template["id"]
33313334
return templates_map
33323335

@@ -4271,7 +4274,7 @@ def __init__(
42714274
self._project = project
42724275
self._folder = folder
42734276
self._folder_path = folder_path
4274-
self._settings = settings
4277+
self._settings = settings.get_all()
42754278
self._s3_repo = s3_repo
42764279
self._backend_client = backend_client
42774280
self._image_quality_in_editor = image_quality_in_editor

src/superannotate/lib/infrastructure/controller.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,16 @@
3030
from lib.infrastructure.services import SuperannotateBackendService
3131

3232

33-
class BaseController:
33+
class SingleInstanceMetaClass(type):
34+
_instances = {}
35+
36+
def __call__(cls, *args, **kwargs):
37+
if cls not in SingleInstanceMetaClass._instances:
38+
SingleInstanceMetaClass._instances[cls] = super().__call__(*args, **kwargs)
39+
return SingleInstanceMetaClass._instances[cls]
40+
41+
42+
class BaseController(metaclass=SingleInstanceMetaClass):
3443
def __init__(self, logger, config_path=constances.CONFIG_FILE_LOCATION):
3544
self._config_path = config_path
3645
self._logger = logger
@@ -129,6 +138,10 @@ def s3_repo(self):
129138

130139

131140
class Controller(BaseController):
141+
def __init__(self, logger, config_path=constances.CONFIG_FILE_LOCATION):
142+
super().__init__(logger, config_path)
143+
self._team = None
144+
132145
def _get_project(self, name: str):
133146
use_case = usecases.GetProjectByNameUseCase(
134147
name=name,
@@ -267,7 +280,9 @@ def upload_image_to_s3(
267280
auth_data = self.get_auth_data(project.uuid, self.team_id, folder.uuid)
268281
use_case = usecases.UploadImageS3UseCase(
269282
project=project,
270-
project_settings=ProjectSettingsRepository(self._backend_client, project),
283+
project_settings=ProjectSettingsRepository(
284+
self._backend_client, project
285+
).get_all(),
271286
image_path=image_path,
272287
image=image_bytes,
273288
s3_repo=s3_repo,
@@ -432,8 +447,11 @@ def prepare_export(
432447
return use_case.execute()
433448

434449
def get_team(self):
435-
use_case = usecases.GetTeamUseCase(teams=self.teams, team_id=self.team_id)
436-
return use_case.execute()
450+
if not self._team:
451+
self._team = usecases.GetTeamUseCase(
452+
teams=self.teams, team_id=self.team_id
453+
).execute()
454+
return self._team
437455

438456
def invite_contributor(self, email: str, is_admin: bool):
439457
use_case = usecases.InviteContributorUseCase(
@@ -1149,9 +1167,12 @@ def upload_annotations_from_folder(
11491167
backend_service_provider=self._backend_client,
11501168
annotation_classes=AnnotationClassRepository(
11511169
service=self._backend_client, project=project
1152-
),
1170+
).get_all(),
11531171
pre_annotation=is_pre_annotations,
11541172
client_s3_bucket=client_s3_bucket,
1173+
templates=self._backend_client.get_templates(team_id=self.team_id).get(
1174+
"data", []
1175+
),
11551176
)
11561177
return use_case.execute()
11571178

src/superannotate/lib/infrastructure/services.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class BaseBackendService(SuerannotateServiceProvider):
2020
AUTH_TYPE = "sdk"
2121
PAGINATE_BY = 100
2222
MAX_RETRY = 3
23+
LIMIT = 100
2324

2425
"""
2526
Base service class
@@ -109,7 +110,10 @@ def _get_page(self, url, offset, params=None, key_field: str = None):
109110
if isinstance(data, dict):
110111
if key_field:
111112
data = data[key_field]
112-
return data, data.get("count", 0) - offset
113+
if data.get("count", 0) < self.LIMIT:
114+
return data, 0
115+
else:
116+
return data, data.get("count", 0) - offset
113117
if isinstance(data, list):
114118
return {"data": data}, 0
115119
return {"data": []}, 0

tests/integration/test_preannotation_upload.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99

1010
class TestVectorPreAnnotationImage(BaseTestCase):
11-
PROJECT_NAME = "test vector"
11+
PROJECT_NAME = "TestVectorPreAnnotationImage"
1212
PROJECT_DESCRIPTION = "Example Project test vector pre-annotation upload"
1313
PROJECT_TYPE = "Vector"
1414
TEST_FOLDER_PATH = "data_set/sample_project_vector"

tests/profiling/profiling.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,16 @@
11
import src.superannotate as sa
2-
import time
3-
#
4-
# s = time.time()
5-
#
6-
# sa.get_project_metadata("dev")
7-
#
8-
# e = time.time()
9-
# print(e-s)
10-
# #
11-
import cProfile
12-
import pstats, io
132

3+
import cProfile
4+
import pstats
5+
import io
6+
sa.delete_images("dev")
147

158

9+
sa.upload_images_from_folder_to_project("dev", "/Users/vaghinak.basentsyan/www/superannotate-python-sdk/tests/data_set/sample_project_vector")
1610
pr = cProfile.Profile()
1711
pr.enable()
1812

19-
sa.delete_images("dev")
20-
sa.upload_images_from_folder_to_project("dev", "/Users/vaghinak.basentsyan/www/superannotate-python-sdk/tests/data_set/sample_project_vector")
13+
sa.upload_annotations_from_folder_to_project("dev", "/Users/vaghinak.basentsyan/www/superannotate-python-sdk/tests/data_set/sample_project_vector")
2114

2215
pr.disable()
2316
s = io.StringIO()

0 commit comments

Comments
 (0)