2017-05-03 3 views
1

Wir entwickeln eine Java-Anwendung mit SWT, die virtuelle Tabellen bietet. Testcode, der es ermöglicht, die Anzahl der Tabellenzeilen zwischen 100 und 10M zu ändern, funktioniert in weniger als 100ms unter Windows und OSX, dauert aber einige Sekunden auf Ubuntu 16.04. Jetzt fragen wir uns, ob dies ein Manko der GTK-Implementierung von SWT oder von GTK selbst ist? Gibt es im letzteren Fall einen Unterschied zwischen GTK 2 und GTK 3?Unterstützt GTK 2/3 effiziente virtuelle Tabellen?

Antwort

3

TLDR: Leider GTK des GtkTreeView scheint nicht im virtuellen Modus überhaupt zu unterstützen, und es ist in einer Weise implementiert, die für die große Anzahl von Elementen sehr ineffizient ist. SWT entschied sich für die Implementierung von Table unter Verwendung von GtkTreeView und führte weitere Leistungsprobleme ein.

SWT Table.setItemCount()

Quelle für Table.setItemCount():

  • Repository: http://git.eclipse.org/gitroot/platform/eclipse.platform.swt.git
  • Quelldatei: eclipse.platform.swt\bundles\org.eclipse.swt\Eclipse SWT\gtk\org\eclipse\swt\widgets\Table.java
  • Suche: public void setItemCount (int count) {

Sie, dass auch in VIRTUAL Modus sehen, setItemCount alle Artikel zuteilen wird, einen nach dem anderen, mit OS.gtk_list_store_append():

for (int i=itemCount; i<count; i++) { 
    OS.gtk_list_store_append (modelHandle, iter); 
} 

SWT OS.gtk_list_store_append

Quelle für OS.gtk_list_store_append:

  • Repository: http://git.eclipse.org/gitroot/platform/eclipse.platform.swt.git
  • Quelldatei: eclipse.platform.swt\bundles\org.eclipse.swt\Eclipse SWT\gtk\org\eclipse\swt\widgets\Table.java
  • Suche: public static final void gtk_list_store_append(long /*int*/ list_store, long /*int*/ iter) {

Hier für jedes Element eine Sperre erworben und freigegeben wird und native Methode aufgerufen wird. Ich denke, sie sollten alle Elemente mindestens mit einem einzigen nativen Anruf zugewiesen haben.

public static final void gtk_list_store_append(long /*int*/ list_store, long /*int*/ iter) { 
    lock.lock(); 
    try { 
     _gtk_list_store_append(list_store, iter); 
    } finally { 
     lock.unlock(); 
    } 
} 

GTK gtk_list_store_append

  • Repository: git://git.gnome.org/gtk+
  • Quelldatei: gtk/gtkliststore.c
  • Suche: gtk_list_store_append (GtkListStore *list_store,

Es ruft lediglich gtk_list_store_insert(list_store, iter, -1)

GTK gtk_list_store_insert

  • Repository: git://git.gnome.org/gtk+
  • Quelldatei: gtk/gtkliststore.c
  • Suche: gtk_list_store_insert (GtkListStore *list_store,

Die Tasten g_sequence_insert_before ist, die in eine gsequence einfügt, die a ausgewogener Baum.

void 
gtk_list_store_insert (GtkListStore *list_store, 
       GtkTreeIter *iter, 
       gint   position) 
{ 
    GtkListStorePrivate *priv; 
    GtkTreePath *path; 
    GSequence *seq; 
    GSequenceIter *ptr; 
    gint length; 

    g_return_if_fail (GTK_IS_LIST_STORE (list_store)); 
    g_return_if_fail (iter != NULL); 

    priv = list_store->priv; 

    priv->columns_dirty = TRUE; 

    seq = priv->seq; 

    length = g_sequence_get_length (seq); 
    if (position > length || position < 0) 
    position = length; 

    ptr = g_sequence_get_iter_at_pos (seq, position); 
    ptr = g_sequence_insert_before (ptr, NULL); 

    iter->stamp = priv->stamp; 
    iter->user_data = ptr; 

    g_assert (iter_is_valid (iter, list_store)); 

    priv->length++; 

    path = gtk_tree_path_new(); 
    gtk_tree_path_append_index (path, position); 
    gtk_tree_model_row_inserted (GTK_TREE_MODEL (list_store), path, iter); 
    gtk_tree_path_free (path); 
} 

Leider ist diese Funktion tut viel von Dingen, die nicht notwendig während eines Masseneinsatz sind beispiels es die Länge der Sequenz berechnet jedes Mal (die nicht-triviale Zeitkomplexität hat) wandelt Indizes Iteratoren, Bringt Update-Benachrichtigungen für den Baum, usw. etc.

Ich suchte, fand aber nichts für Masseneinsätze.

Windows-Implementierung

Windows-Implementierung von Table verwendet OS bereitgestellte ListView Steuerung, die effizient für virtuellen Modus implementiert wird auch

See (LVS_OWNERDATA e): Eclipse Bug 236863