Skip to content

[GTK] Speed up Combo setItems/removeAll/remove for large item counts#3401

Draft
vogella wants to merge 1 commit into
eclipse-platform:masterfrom
vogella:gtk-combo-bulk-update-perf
Draft

[GTK] Speed up Combo setItems/removeAll/remove for large item counts#3401
vogella wants to merge 1 commit into
eclipse-platform:masterfrom
vogella:gtk-combo-bulk-update-perf

Conversation

@vogella

@vogella vogella commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Setting or clearing a large number of Combo items (>5000) is very slow on GTK because GtkComboBox recomputes its popup and cell-view layout on every single model change.
This detaches the GtkListStore during the bulk setItems, removeAll and remove(start, end) operations and re-attaches it once, so the widget relayouts a single time instead of once per row.
The active selection is preserved across range removals, and a new Combo test covers that selection handling.

This adds one native binding (gtk_combo_box_set_model), so it needs the GTK3 and GTK4 CI runs to validate the native build and behavior; it could not be compiled or tested locally.

Fixes #506

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Test Results

  200 files  ±0    200 suites  ±0   25m 55s ⏱️ - 3m 16s
4 743 tests +1  4 719 ✅ +1   24 💤 ±0  0 ❌ ±0 
6 886 runs  +6  6 718 ✅ +6  168 💤 ±0  0 ❌ ±0 

Results for commit 924ec33. ± Comparison against base commit 450ece0.

♻️ This comment has been updated with latest results.

Setting or removing a large number of combo items (>5000) was very slow on
GTK because GtkComboBox recomputes its popup/cell-view layout on every single
model change, leading to O(n^2)/O(n) per-row overhead.

Detach the GtkListStore model from the combo box before bulk modifying it
(setItems, removeAll and remove(start, end)) and re-attach it afterwards, so
the widget reacts only once. setItems now populates the GtkListStore directly
instead of going through the per-item GtkComboBoxText convenience function.
remove(start, end) restores the active selection after re-attaching, adjusted
for the rows removed before it.

Adds the gtk_combo_box_set_model native binding and drops the now-unused
gtk_combo_box_text_remove_all binding.

Fixes eclipse-platform#506

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves GTK Combo performance for large bulk updates by avoiding repeated GtkComboBox relayouts on every single row change. It does so by temporarily detaching the GtkListStore model during setItems, removeAll, and range remove(start, end), then reattaching it once, and it adds a GTK-only unit test to validate selection preservation behavior for range removals.

Changes:

  • Detach/reattach the GtkComboBox model during bulk Combo mutations to reduce relayout work on GTK.
  • Preserve and restore the active selection across remove(start, end) when the selected item is outside the removed range.
  • Add a new GTK native binding (gtk_combo_box_set_model) and a GTK-only JUnit test for selection handling.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_widgets_Combo.java Adds a GTK-only test to validate selection behavior around range removals.
bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Combo.java Implements model detachment for bulk operations and restores selection for range removes.
bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/GTK.java Adds gtk_combo_box_set_model binding and removes gtk_combo_box_text_remove_all binding.
bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os.c Adds JNI bridge for gtk_combo_box_set_model and removes JNI bridge for gtk_combo_box_text_remove_all.
bundles/org.eclipse.swt/Eclipse SWT PI/gtk/library/os_stats.h Updates native function stats enum for the added/removed GTK JNI bindings.

Comment on lines +2080 to +2098
OS.g_object_ref (model);
gtk_combo_box_toggle_wrap (false);
GTK.gtk_combo_box_set_model (handle, 0);
long iter = OS.g_malloc (GTK.GtkTreeIter_sizeof ());
for (int i = end; i >= start; i--) {
if (GTK.gtk_tree_model_iter_nth_child (model, iter, 0, i)) {
GTK.gtk_list_store_remove (model, iter);
}
}
OS.g_free (iter);
GTK.gtk_combo_box_set_model (handle, model);
if (newIndex != -1) {
// Restore the selection without firing a spurious Modify event.
OS.g_signal_handlers_block_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
GTK.gtk_combo_box_set_active (handle, newIndex);
OS.g_signal_handlers_unblock_matched (handle, OS.G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, CHANGED);
}
OS.g_object_unref (model);
gtk_combo_box_toggle_wrap (true);
Comment on lines +2144 to +2150
OS.g_object_ref (model);
gtk_combo_box_toggle_wrap (false);
GTK.gtk_combo_box_set_model (handle, 0);
GTK.gtk_list_store_clear (model);
GTK.gtk_combo_box_set_model (handle, model);
OS.g_object_unref (model);
gtk_combo_box_toggle_wrap (true);
Comment on lines +2444 to +2455
OS.g_object_ref (model);
gtk_combo_box_toggle_wrap (false);
GTK.gtk_combo_box_set_model (handle, 0);
GTK.gtk_list_store_clear (model);
long iter = OS.g_malloc (GTK.GtkTreeIter_sizeof ());
for (int i = 0; i < items.length; i++) {
gtk_list_store_insert (model, iter, items [i], i);
}
OS.g_free (iter);
GTK.gtk_combo_box_set_model (handle, model);
OS.g_object_unref (model);
gtk_combo_box_toggle_wrap (true);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

setting/removing large number of (more than 5000) combo items is too slow

2 participants