TreeViewer ленивая загрузка только иконки - PullRequest
0 голосов
/ 01 марта 2011

У меня есть TreeViewer, он отображает список элементов. Мои ограничения следующие:

  • Каждый элемент представлен в виде XML-файла на диске.
  • Имя файла каждого XML-файла является меткой для значка («hello.xml» -> элемент «привет» в дереве)
  • Каждый файл XML имеет «тип», хранящийся в XML, это представляет изображение для каждого элемента

Когда я выполняю getChildren () для элементов TreeViewer, я читаю в каждом файле XML и генерирую оттуда массив Object []. До недавнего времени это было приемлемо, но это больше не так. Нормальное количество файлов XML было 10, теперь оно 500.

Мне нужно улучшить производительность. Однако по ряду причин, таких как совместимость, следующие опции невозможны

  • Невозможно изменить формат файлов XML (т. Е. Использовать базу данных, сериализованный объект ..)
  • Невозможно создать дополнительное представление файлов XML
  • Невозможно изменить имя XML-файлов (например, hello.xml -> hello-type.xml '

Исходя из моих тестов, разумная производительность обнаруживается при получении списка каталогов XML-файлов и использовании его для меток. Название метки является наиболее важным аспектом, и хотя тип изображения полезен, его наличие не требуется немедленно.

Эти требования и ограничения привели меня к следующему решению:

  1. Первоначально getChilren () сканирует каталог файлов XML и возвращает список меток с изображением «отсутствующего» типа. (getImage () = missingImage)
  2. getChilren () затем запускает фоновое задание, которое читает файлы XML и получает тип.
  3. Каждый объект [] имеет метод cacheImage (), который загружается в изображение типа (поэтому теперь getImage () == ProperIcon). Это называется Иов.
  4. Затем Job выполняет итерацию по каждому элементу дерева и вызывает update () для каждого элемента

Я реализовал это, и производительность оставляет желать лучшего. Кроме того, поскольку у нас так много вызовов Display.getDefault (). AsyncExec, чтобы выполнить обновление, GUI (хотя и остается отзывчивым) потребует времени, чтобы ответить на взаимодействия с пользователем (хотя фактически не блокируется). Есть ли способы, которыми я могу улучшить это?

Было рассмотрено / опробовано следующее:

  • Использовать DeferredTreeContentManager - не сделал этого, потому что сначала я хочу быстро и быстро получить имена, изображения могут последовать позже в своем собственном темпе
  • Выполнение обновления () для всех элементов одновременно / пакетирование элементов - это блокирует графический интерфейс, что хуже, чем для многих отдельных обновлений ()

Ответы [ 4 ]

1 голос
/ 02 марта 2011

Попробуйте понизить приоритет вашего фонового потока, вызвав

this.setPriority(this.getPriority()-1);

в ваших Thread.

500 вызовах на asyncExec, которые не делают GUI без ответа, если онине более чем установка изображения в TreeItem.Чтобы ваши звонки на TreeViewer.update были дешевыми, позвоните по номеру

TreeViewer.setUseHashlookup(true)

, что позволяет эффективно сопоставлять элементы с TreeItems.

0 голосов
/ 11 марта 2011

Я бы посоветовал загрузить / создать несколько изображений одновременно в фоновом потоке (из того, что вы сказали, звучит так, как будто вы можете сделать не менее 10 без проблем с производительностью). Таким образом, ваша тема будет выглядеть примерно так:

// Load/Create some number of images...

Display.asyncExcec(new Runnable() {
    public void run() {
        getTreeViewer().setRedraw(false);
        // Loop and call update on each node you loaded the image for
        getTreeViewer().setRedraw(true);
    }
});
0 голосов
/ 01 марта 2011

Я бы рекомендовал следующие стратегии оптимизации (по порядку) ...

  1. Пакетное обновление звонков. То есть, есть список, в который вы помещаете контентные объекты, изображение которых было рассчитано. Когда размер списка достигает определенного порогового значения (или у вас заканчиваются объекты), начните обновление всех объектов, представленных в списке. Обязательно сначала скопируйте содержимое списка и очистите список, чтобы поток кеширования продолжал накапливаться. Поиграйте с пороговым параметром, и вы, вероятно, получите желаемую производительность, уменьшив количество вызовов asyncExec.

  2. Если # 1 само по себе недостаточно (маловероятно), вы также можете рассмотреть возможность оптимизации в видимой области. Класс Tree имеет API для отслеживания видимых элементов, и вы можете прослушивать события прокрутки. Идея здесь в том, чтобы расставить приоритеты при расчете изображений для видимых элементов и вызывать обновление для элементов только после того, как они станут видимыми.

0 голосов
/ 01 марта 2011

Не поможет ли это, если вы загрузите все изображения в ImageRegistry в фоновом режиме (возможно, с использованием XML), а затем просто добавите изображения из этого реестра?

...