atauenis / fcmd

The File Commander is a modern cross-platform two panel file manager, written in C#.
Other
42 stars 9 forks source link

Тормозит ListView2 #19

Open atauenis opened 10 years ago

atauenis commented 10 years ago

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

atauenis commented 10 years ago

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

atauenis commented 10 years ago

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

atauenis commented 10 years ago

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

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

wilbit commented 10 years ago

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

atauenis commented 10 years ago

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

atauenis commented 10 years ago

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

Break-Neck commented 10 years ago

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

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

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

atauenis commented 10 years ago
  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 сек. на средней системе).

wilbit commented 10 years ago

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

atauenis commented 10 years ago

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

wilbit commented 10 years ago

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

atauenis commented 10 years ago

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

Break-Neck commented 10 years ago

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

Break-Neck commented 10 years ago

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

atauenis commented 10 years ago

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

Break-Neck commented 10 years ago

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

atauenis commented 10 years ago

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

wilbit commented 10 years ago

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

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