darktable-0001: map_locations image diff g_list_find O(N*M) MEDIUM 375x darktable-0002: tags _tag_add_tags_to_list g_list_find O(T*L) MEDIUM 375x darktable-0003: map view clustering g_list_find(sel_imgs) O(I²×S) HIGH 160x scribus-0001: getSortedStyleList retList.contains O(N²) MEDIUM 167x (×4 copies) scribus-0002: getUsedPatterns results.contains O(I×R) MEDIUM 98x scribus-0003: Selection::addItems m_SelList.contains O(N×M) MEDIUM 2100x
58 lines
2.7 KiB
Diff
58 lines
2.7 KiB
Diff
# UNDF: UNDF-2026-000000797
|
||
# UNDF: (leave blank)
|
||
# darktable-0003: map view clustering g_list_find(sel_imgs) inside O(I*J) loop
|
||
#
|
||
# In src/views/map.c, the map clustering code iterates over all images (i-loop)
|
||
# and for each cluster, iterates again over all images (j-loop). Inside the
|
||
# j-loop, g_list_find(sel_imgs, GINT_TO_POINTER(p[j].imgid)) performs a linear
|
||
# scan of the selected-images list (length S). Total complexity: O(I*J*S)
|
||
# which for 5000 map images with 500 selected is O(5000*5000*500) = 12.5
|
||
# billion pointer comparisons.
|
||
#
|
||
# The outer i-loop also calls g_list_find(sel_imgs, ...) for NOISE points
|
||
# and cluster heads — each O(S), contributing O(I*S) additional.
|
||
#
|
||
# Fix: build a GHashTable from sel_imgs before the loop, replace g_list_find
|
||
# with g_hash_table_contains for O(1) lookup.
|
||
#
|
||
# Severity: HIGH — map view is redrawn on every pan/zoom with the full image
|
||
# collection; O(I²×S) collapses to O(I²+S).
|
||
--- a/src/views/map.c
|
||
+++ b/src/views/map.c
|
||
@@ -1506,6 +1506,12 @@
|
||
gboolean *processed = calloc(num_clusters+1,sizeof(gboolean));
|
||
GList *sel_imgs = dt_act_on_get_images(FALSE, FALSE, FALSE);
|
||
+
|
||
+ // Build hash set for O(1) selection membership test
|
||
+ GHashTable *sel_set = g_hash_table_new(g_direct_hash, g_direct_equal);
|
||
+ for(GList *si = sel_imgs; si; si = g_list_next(si))
|
||
+ g_hash_table_add(sel_set, si->data);
|
||
+
|
||
int group = -1;
|
||
for(i = 0; i< img_count; i++)
|
||
{
|
||
@@ -1523,8 +1529,7 @@
|
||
if(sel_imgs)
|
||
- entry->selected_in_group = g_list_find((GList *)sel_imgs,
|
||
- GINT_TO_POINTER(entry->imgid))
|
||
- ? TRUE : FALSE;
|
||
+ entry->selected_in_group =
|
||
+ g_hash_table_contains(sel_set, GINT_TO_POINTER(entry->imgid));
|
||
lib->images = g_slist_prepend(lib->images, entry);
|
||
@@ -1540,8 +1545,7 @@
|
||
- entry->selected_in_group = (sel_imgs && g_list_find((GList *)sel_imgs,
|
||
- GINT_TO_POINTER(p[i].imgid)))
|
||
- ? TRUE : FALSE;
|
||
+ entry->selected_in_group = sel_imgs
|
||
+ && g_hash_table_contains(sel_set, GINT_TO_POINTER(p[i].imgid));
|
||
@@ -1557,7 +1561,7 @@
|
||
if(sel_imgs && !entry->selected_in_group)
|
||
{
|
||
- if(g_list_find((GList *)sel_imgs, GINT_TO_POINTER(p[j].imgid)))
|
||
+ if(g_hash_table_contains(sel_set, GINT_TO_POINTER(p[j].imgid)))
|
||
entry->selected_in_group = TRUE;
|
||
}
|
||
}
|
||
free(processed);
|
||
+ g_hash_table_destroy(sel_set);
|
||
g_list_free(sel_imgs);
|