fcmd icon indicating copy to clipboard operation
fcmd copied to clipboard

Тормозит ListView2

Open atauenis opened this issue 10 years ago • 18 comments

На больших каталогах FileListpanel, в основе которого лежит ListView2, ощутимо тормозит. Предположительной причиной является изъян архитектуры ListView2Item, где для каждого дела в HBox добавляется по виджету.

atauenis avatar Jul 17 '14 17:07 atauenis

Итак, было опробовано заменить создание виджетов на OnDraw (для справки - override void OnDraw, это аналог обработчика события Paint в Windows Forms и аналогичных тулкитах). Результат оказался ненамного лучше. И это на примитивнейшем варианте, без иконок, закраски фона, жёстко зашитом размером строки и т.д.. Вероятно, добавление иконок, фона, обработки кликов, переименования файлов и подобного функционала текущего варианта скорость уменьшит до уровня оригинала. Ищутся другие варианты...

atauenis avatar Jul 17 '14 17:07 atauenis

Посмотрел на внешние признаки работы листвью в Total Commander (без дизассемблирования). По всей видимости, там применено: 1.) Прямая отрисовка, т.к. win32 window не просматриваются глубже самого "LCLListBox". 2.) Строки не прокручиваются, а перерисовываются. Т.е. на экране всегда одно количество строк, равное количеству вмещающихся, во время прокрутки заменяется их содержимое (по всей видимости, используется многопоточный метод работы, т.к. при быстрой прокрутке не подвисает, а только кратковременно выводит пустоту). Считаю данную архитектуру годной для применения в FC.

atauenis avatar Jul 18 '14 09:07 atauenis

Осталось сделать прокрутку перетасовыванием содержимого ListView2Item'ов (сейчас они тупо перемещаются за пределы экрана). Ещё есть проблема с GTK, надо как-то сделать пониже z-index у lv2i, т.к. последние закрывают полосы прокрутки. А z-index в XWT похоже нет )))

~~Ещё есть момент, что не умещающиеся по длинне надписи закрывают расположенные справа от них.~~ UPD 23/07: Устранено в 9a70e0a.

atauenis avatar Jul 22 '14 18:07 atauenis

Подозреваю, что в tcmd используется виртуализация панели, чтоб не отрисовывать все эелементы (классическая проблема прокручивающихся списков).

wilbit avatar Jul 30 '14 10:07 wilbit

Именно так и планируется сделать. Есть массив элементов каталога, FS.DirectoryContent, из которого и нужно брать данные. Затык в том, как грамотнее определить список необходимых для отображения DirItem'ов (окно может менять размер, не пересчитывать же virtual ListView2 при изменении его размера на каждый 1 px).

atauenis avatar Jul 30 '14 11:07 atauenis

После #25 производительность LV2 увеличилась в разы. Но большие каталоги загружаются более чем за 1 сек, что неприемлемо. Виртуальный режим всё же необходим.

atauenis avatar Aug 05 '14 09:08 atauenis

Решил посмотреть, что можно сделать, пара вопросов:

  1. Активность интерфейса при загрузке директории -- это принципиальная позиция? Тот же Total Commander позволяет себе включить "часики".
  2. Вытекает из предыдущего: если на время загрузки сделать окно постоянного размера?

И еще 1 проблема, возможно, связанная с ListView2 -- при 20000 файлов возникает такая штука: screen При 10000 ее нет.

Break-Neck avatar Aug 10 '14 17:08 Break-Neck

  1. Не совсем. Обилие DispatchPendingEvents (вернее, автоматически заменённые Search&Replace Visual Studio вызовы winforms.Application.DoEvents, это прямой аналог DPE) это не убранный временный код 2013 года, когда алгоритм загрузки каталогов имел свойство подвисать в бесконечных циклах. Сейчас уже можно допустить "часики". Но каждые 2-3 секунды надо обязательно делать DPE, чтобы пользователь мог закрыть окно штатным образом. При этом надо убрать Spinner, т.к. он не вращается при подвисании потока UI (отрисовка), вместо него предусмотреть кнопку остановки загрузки.
  2. Одобряю.

И еще 1 проблема, возможно, связанная с ListView2 -- при 20000 файлов возникает такая штука

Похоже, это баг Xwt Table. Кстати, такая же петрушка есть и при 1000 файлов, но через 0,5 секунд всё само расставляется как надо. От Table надо отказываться, хотя бы в пользу Vbox (а лучше на самописный вариант, отрисовывающий кусками по 50-100 файлов, т.е. каждые 0,5 сек. на средней системе).

atauenis avatar Aug 10 '14 18:08 atauenis

А сколько времени у вас занимает отрисовка видимой части панели? Надо выносить чтение каталога в отдельный поток, а панель виртуализировать.

wilbit avatar Aug 11 '14 03:08 wilbit

998 файлов и папок за 5,592 сек., из которых на парсинг каталога уходит 2,19 сек. 70 файлов и папок 0,39 сек, из которых парсинг 0,276. Т.е. основная проблема именно в отрисовке. Как я уже писал, надо избавляться от Table. Замена ему должна уметь размещать виджеты произвольно по сетке, т.к. требуется чёткое позиционирование виджетов по двум осям (в перспективе для режима "значки", "эскизы" и т.п.). В прочем, это даже облегчает написание виртуализиции. ;-)

atauenis avatar Aug 11 '14 08:08 atauenis

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

wilbit avatar Aug 11 '14 08:08 wilbit

Мне кажется, обе проблемы должен решить виртуальный режим с подгрузкой необходимой части списка файлов напрямую от плагина FS (благо на небольших объёмах входной информации, а они в виртуальном режиме большими быть не могут, текущий метод формирования ListView2Item'ов и их добавления на ListView2 работает удовлетворительно).

atauenis avatar Aug 11 '14 08:08 atauenis

Угу, надо реализовать ассинхронную подгрузку, а в ListView2 держать не больше 100 элементов, подгружая их по мере надобности.

Break-Neck avatar Aug 11 '14 10:08 Break-Neck

Полез реализовывать, но столкнулся с определенной проблемой: при фоновом чтении каталога нельзя (по крайней мере, очевидным мне способом), показывать долю загруженных файлов и директорий. Нормально это выкинуть?

Break-Neck avatar Aug 11 '14 18:08 Break-Neck

Нет. Пользователь должен видеть, сколько ещё осталось "загрузить" (актуально при чтении больших каталогов через сеть или с дискет).

atauenis avatar Aug 11 '14 19:08 atauenis

Проблема в том, что, если я загружаю содержимое папки в фоне, то я не могу предсказать, сколько в ней всего файлов.

Break-Neck avatar Aug 11 '14 19:08 Break-Neck

Ну, если никак, можете убрать все RaiseProgressChanged и RaiseStatusChanged, чтобы не вылезало уведомление о процессе загрузки. Будут песочные часы, этого достаточно (за 20 лет существования Windows/Total Commander, даже во времена дискет и dial-up, никто не жаловался :-) ).

atauenis avatar Aug 11 '14 19:08 atauenis

Похоже, это баг Xwt Table. Кстати, такая же петрушка есть и при 1000 файлов, но через 0,5 секунд всё само расставляется как надо. От Table надо отказываться, хотя бы в пользу Vbox (а лучше на самописный вариант, отрисовывающий кусками по 50-100 файлов, т.е. каждые 0,5 сек. на средней системе).

Займусь этим #28.

wilbit avatar Aug 15 '14 08:08 wilbit