我们正在使用SWT开发一个Java应用程序,它提供了虚拟表。允许在100和10M之间切换表行数的测试代码在Windows和OSX上的工作时间不到100毫秒,但在Ubuntu 16.04上需要几秒钟。现在我们想知道这是否是SWT GTK实施或GTK本身的缺点?在后一种情况下,GTK 2和GTK 3之间是否存在差异?
答案 0 :(得分:3)
TLDR:不幸的是,GTK的GtkTreeView似乎根本不支持虚拟模式,而且它的实现方式对于大量项目效率非常低。 SWT选择使用Table
实施GtkTreeView
并引入了进一步的性能问题。
SWT Table.setItemCount()
Table.setItemCount()
的来源:
http://git.eclipse.org/gitroot/platform/eclipse.platform.swt.git
eclipse.platform.swt\bundles\org.eclipse.swt\Eclipse SWT\gtk\org\eclipse\swt\widgets\Table.java
public void setItemCount (int count) {
您会看到即使在VIRTUAL
模式下,setItemCount
也会使用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
OS.gtk_list_store_append
的来源:
http://git.eclipse.org/gitroot/platform/eclipse.platform.swt.git
eclipse.platform.swt\bundles\org.eclipse.swt\Eclipse SWT\gtk\org\eclipse\swt\widgets\Table.java
public static final void gtk_list_store_append(long /*int*/ list_store, long /*int*/ iter) {
这里,对于每个项目,获取并释放锁定并调用本机方法。我猜他们应该至少用一个原生呼叫分配所有项目。
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
git://git.gnome.org/gtk+
gtk/gtkliststore.c
gtk_list_store_append (GtkListStore *list_store,
它只是调用gtk_list_store_insert(list_store, iter, -1)
GTK gtk_list_store_insert
git://git.gnome.org/gtk+
gtk/gtkliststore.c
gtk_list_store_insert (GtkListStore *list_store,
关键操作是g_sequence_insert_before
,插入gsequence,这是一棵平衡树。
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);
}
不幸的是,这个函数很多在批量插入过程中不需要的东西,例如它每次计算序列的长度(具有非常复杂的时间复杂度),将索引转换为迭代器,触发树的更新通知等等。
我搜索过,但没有找到任何批量插入内容。
Windows实施
Table
的Windows实现使用操作系统提供的ListView
控件,该控件在虚拟模式下有效实现(参见LVS_OWNERDATA
)
另请参阅:Eclipse Bug 236863