Skip to content

[GTK] problematic runtime behavior in table when deleting many rows #3607

Description

@wnesensohn

On GTK3, deleting many rows from a table results in a hang if

  • SWT_MULTI is set
  • the rows to be deleted intersect with the selection of the table
  • the number of rows to be deleted is relatively large

Snippet:

import org.eclipse.swt.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class GtkTablePerformanceIssue {
	private static final int HUGE_COUNT = 500_000;
	private static final int LARGE_COUNT = 50_000;
	private static final int SMALL_COUNT = 5;

	public static void main(String[] args) {
		final Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setText("GTK Table remove performance");
		shell.setLayout(new GridLayout(1, false));

		final Table table = new Table(shell, SWT.VIRTUAL | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		table.addListener(SWT.SetData, event -> {
			final TableItem item = (TableItem)event.item;
			item.setText("Item " + table.indexOf(item));
		});

		final Label explanation = new Label(shell, SWT.NONE);
		explanation.setText("When shrinking, select a row which won't exist after the shrink.");

		final Button huge = new Button(shell, SWT.PUSH);
		huge.setText("Reset to " + HUGE_COUNT + " rows");
		huge.addListener(SWT.Selection, event -> table.setItemCount(HUGE_COUNT));

		final Button large = new Button(shell, SWT.PUSH);
		large.setText("Reset to " + LARGE_COUNT + " rows");
		large.addListener(SWT.Selection, event -> table.setItemCount(LARGE_COUNT));

		final Button shrink = new Button(shell, SWT.PUSH);
		shrink.setText("Shrink to " + SMALL_COUNT + " rows");
		final Label result = new Label(shell, SWT.NONE);
		result.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		shrink.addListener(SWT.Selection, event -> {
			final long start = System.nanoTime();
			table.setItemCount(SMALL_COUNT);
			final long elapsedMillis = (System.nanoTime() - start) / 1_000_000;
			result.setText("setItemCount(" + SMALL_COUNT + "): " + elapsedMillis + " ms");
			result.getParent().layout();
		});

		table.setItemCount(LARGE_COUNT);
		table.select(8);
		shell.setSize(500, 400);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		display.dispose();
	}
}

Expected behavior
The entries should be removed as fast as they are when only the first row is selected.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions