GtkTreeView снижение производительности вставки / обновления из-за сортировки - PullRequest
6 голосов
/ 23 августа 2010

У меня проблемы с производительностью при вставке многих строк в древовидную структуру GTK (с использованием PyGTK) или при изменении многих строк.Проблема в том, что модель, кажется, восстанавливается после каждого изменения (вставка / модификация).Это приводит к зависанию графического интерфейса на несколько секунд.Оставив несортированную модель, закомментировав model.set_sort_column_id(SOME_ROW_INDEX, gtk.SORT_ASCENDING), вы устраните эти проблемы.

Поэтому я хотел бы отключить сортировку, пока я вставляю или изменяю модель, и включить ее позже.К сожалению, сортировку нельзя отключить с помощью model.set_sort_column_id(-1, gtk.SORT_ASCENDING).Использование функций замораживания / оттаивания также не работает:

treeview.freeze_child_notify()

try:
    for row in model:
        # ... change something in row ...
finally:
    treeview.thaw_child_notify()

Итак, как я могу отключить сортировку?Или есть лучший способ для массовых вставок / модификаций?


Решение

Благодаря информации и ссылкам, предоставленным bobince в его ответе, я проверил некоторыеиз альтернатив:

1) Макетная сортировка

 tv.freeze_child_notify()
 sortSettings = model.get_sort_column_id()
 model.set_default_sort_func(lambda *unused: 0) # <-- can also use None but that is slower!
 # model.set_default_sort_func(lambda *unused: 1) <-- slow
 # model.set_default_sort_func(lambda *unused: -1) <-- crash (access violation in gtk_tree_store_move_after?!)
 model.set_sort_column_id(-1, gtk.SORT_ASCENDING)
 # change rows
 model.set_sort_column_id(*sortSettings)
 tv.thaw_child_notify()

Это привело к сокращению времени с примерно 11 секунд до 2 секунд.Вот Это Да!Но могло быть и лучше, это было только для 1000 строк.

2) Удаление модели при обновлении

tv.set_model(None)
# change rows
tv.set_model(model)

Нет заметной разницы, 11 секунд.

3) Фиктивная сортировка и трюк с классным генератором из PyGTK FAQ

 def gen():
      tv.freeze_child_notify()
      sortSettings = model.get_sort_column_id()
      model.set_default_sort_func(lambda *unused: 0)
      model.set_sort_column_id(-1, gtk.SORT_ASCENDING)

      i = 0
      for row in rowsToChange:
           i += 1
           # change something
           if i % 200 == 0:
                # freeze/thaw not really  necessary here as sorting is wrong because of the
                # default sort function
                yield True

      model.set_sort_column_id(*sortSettings)
      tv.thaw_child_notify()
      yield False

 g = gen()
 if g.next(): # run once now, remaining iterations when idle
     gobject.idle_add(g.next)

Результат: те же 2 секунды, что и в решении 1),но графический интерфейс реагирует в течение этого времени.Я предпочитаю этот метод.Modulo 200 может быть настроен, чтобы сделать графический интерфейс более или менее реактивным, если это необходимо.

Может быть, даже возможно создать подкласс gtk.TreeStore, чтобы получить лучшие результаты?Еще не пробовал, но вариант 3) пока достаточно.

1 Ответ

2 голосов
/ 24 августа 2010

Звучит так, будто ты почти у цели.См. FAQ для дальнейших заметок.В частности, вы должны также установить default_sort_order (теперь вы можете использовать None, а также фиктивную лямбду сравнения в этом примере для повышения производительности), чтобы гарантировать отсутствие сортировки, и удалить модель из древовидной структурыпродолжительность операций.

Если изменений много, вам лучше создать и настроить новую модель.

...