Pull to refresh

Comments 39

А, да, к последнему надо дописать:
             <tk:DataGrid x:Name="dataGrid" 
             ItemsSource="{Binding Path=Bookings}" 
             AutoGenerateColumns="False" 
             EnableRowVirtualization="True" 
             EnableColumnVirtualization="True"
             VirtualizingStackPanel.IsVirtualizing="True">
Спасибо.
Я попробовал грид из Xceed. Он показал в моем тесте в 3 раза больший FPS чем стандартный грид WPF.

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

Как можно заставить этот грид отображать содержимое во время скроллинга? (иначе сложно адекватно сравнить его с остальными)
Не помогает. Всеравно не отрисовывает содержимое до остановки скроллинга…
И вообще, если хотите быстро-быстро, то берите fastwpfgrid.codeplex.com, он не создаёт Visual Tree, а рисует сам. Насколько я понимаю, примерно так же делает FTLK.
К сожалению сейчас не могу проверить. Грид не совместим с vs2010 и .net framework 4.0
(даже не получается перестроить грид из исходников без более свежей студии и 4.5.1, а на этой машине не могу его сносить 4.0 так на ней иногда как требуется строить приложения совместимые с XP, для которой нет 4.5.1)

Попробую проверить на более свежем framework позже. По исходникам могу сказать что в реализации грида много unmanaged кода, и приложеный пример (который в бинарном виде запускается даже на 4.0) работает в два раза быстрее стандартного грида WPF, однако же в примере 100 колонок и 1000 строк, что отличается от тестовой конфигурации.

Кроме того опасения вызывает то, что контрол fastgrid достаточно «молодой», появился только в Mar 24, 2015, есть риск столкнуться с багами при использованиии в продакшине…

Я попробую его чуть позже, когда будет доступна ситема, где нет необходимости в 4.0 фреймворке.
много unmanaged кода
Где? Всё на шарпе и компилится в msil.
Да, я не правильно выразился. не unmanaged, а unsafe в проекте WriteableBitmapEx.
Конкретно этой библиотеке похоже уже 3 года, и вполне возможно, что она достаточно «провереная». Хотя конечно код вроде этого, немного пугает с точки зрения использования в С#
// Win32 memory copy function
//[DllImport(«ntdll.dll»)]
[DllImport(«msvcrt.dll», EntryPoint = «memcpy», CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
public static extern unsafe void* memcpy(
void* dst,
void* src,
int count);

В любом случае грид заметно быстрее стандартного. Надо его проверить с тестовыми данными.
Попробовал использовать FastGridControl в своем примере вместо стандартного грида. Я просто подставил другой грид в свой тест и грид на системе с 4.5.1 все заработало.

Производительность была ровно такой-же как и и обычного грида WPF. (да похоже это и был обычный WPF грид)
Видимо в приложенных примерах с гридом делается еще что-то, причем со стороны приложения, что его использует.

В примере, которые лежит в репозитории видно что еще создаются дополнительные модели и некий свой TextRenderPanel контрол (очень странно почему все это делается не внутри грида, а снаружи)

Похоже повозиться тут надо не меньше чем с FLTK. Но все еще не теряю надежды запустить данный грид, так, чтобы он работал быстро, однако похоже для этого надо будет потратить немало времени.
Я наконец таки его запустил так, чтобы он работал быстро.

Возиться пришлось не меньше чем с FLTK: создать модель представления и использовать кастомный рендер текста и фиксированный размер грида. Кроме того пришлось отказаться от биндингов данных.

Но все же fastwpfgrid показал производительность примерно равную производительности грида FLTK.

Конечно это очень хороший результат, хотя грид и не дешев в использовании.
Жалко что грид пока слишком молодой (4 месяца и 231 скачка) для использования в продакшине.
Еще более жалко что стандартный грид WPF не дает и половины производительности этого грида…
Попробуйте из описанных фиксов оставить только фиксированные размеры грида. Остальное — семечки, по сравнению с UpdateLayout().
Можеие в dotTrace поглядеть на чем просадка производительности в случае с DataGrid. Там при ресайзе ужасно много UpdateLayout вызывается, хотя визуально разницы может быть почти не видно.
Ранее я пробовал ставить фиксированные размеры WPF гридам. Эффекта от этого не было. Грид вызывает измерение размера ячеек даже тогда, когда причины для измерений нет… то есть нет ни ресайза, ни изменения колонок — только скроллинг.
Под фиксированным размером грида я подразумевал прежде всего ширины колонок. Специально писал плагин к нему, который рулит этими ширинами. Те же резиновые колонки получались, но обновлялись ширины с нужной мне частотой (с задержкой).
Если вообще задать фиксированные ширины колонкам и не трогать их, то производительность сильно поднимается.
Удалось ли вам запретить «лишние» вызовы стандартного MeasureCore во время скроллинга грида? Если да, то как?
>Штатный WPF-ный грид умеет кучу совершенно ненужных в типовом приложении вещей
Что не делает ему чести, если это нельзя быстро и легко отключить.
Стоковый грид только на старте, только с дефолтными типами колонок (не TemplateColumn) и только с виртуализацией.
Его проблема в очень сложном визуальном дереве, что вместе с адаптивным дизайном (подгонка ширины колонок под контент) убивает производительность напроч.
Я профайлил стартовый этам и даже на глаз заметно, что при первом рендеринге экрана колонки несколько раз меняют свой размер. При каждом ресайзе вызывается огромное количество Measure() для вычисления размеров всех элементов в дереве.

Не думаю что от стокового грида вряд ли кто-то ожидал хорошей работы. Да, он содержит в себе чрезмерное количество фич, которые реализованы криво и зачастую не нужны.
В статье я рассматривал этап уже не стартовый этап, и даже не менял размеры колонок.
Я просто скролил контент.

И кстати ранее тоже профайлил WPF грид во время скролла (в комментах к предыдущей статье я это разбирал). Вот например мой скриншот профайлинга во время скролла
http://s30.postimg.org/4lvgfhrnl/Measure.png

Большинство времени тратится на MeasureCore, даже тогда когда никакие размеры ни грида ни колонок не меняются, виртуализация проблему не лечит.

Выглядит такая логика не эффективной конечно т.е. можно сказать что проблема в реализации грида.
Именно в реализации и конкретно в поведении лэйаута и глубины визуального дерева. Это один из самых тормозных стоковых компонентов.
А что по поводу виртуализации? Без нее WPF (про остальные UI не в курсле) неподъёмен, известное дело.
По дефолту DataGrid её использует. Можно включить реиспользование через VirtualizingStackPanel.VirtualizationMode="Recycling"
VirtualizingStackPanel.VirtualizationMode=«Recycling» — добавил для примера WPF. Изменений в результате не видно…
У DataGrid и с виртуализацией проблемы производительности серьезные (адаптивный лэйаутинг). Но в кейсе описанном в статье колонки, если не ошибаюсь, не изменяют свой размер.
Вот если бы сравнили с ListView + GridView. Да еще бы в кейсе перезаполнения источника данных, тогда было бы интереснее.
DataGrid — Угрюмое Гуано. Нехорошая кандидатура для сравнения.
Как понимаю, основной недостаток ListView + GridView в невозможности полноценного inline edit.

Был бы рад, если бы кто-нибудь написал подобное сравнение для контролов ListView в разных библиотеках и возможно других стандартных контролов. Гриды же были выбраны мной, как наиболее универсальные контролы представления (и редактирования) табличных данных.
Ответил ниже
Отличием DataGrid от ListView является то, что у него предоставлено API для редактирования. Т.е. вы у него снаружи прописываете два шаблона ячейки: шаблон для чтения и шаблон для редактирования.
В моей практике по требованию от UX и дизайнера часто приходится реализовывать хитрое поведение ячеек. Например могут потребовать чтоб все ячейки одновременно переходили в режим редактирования. Потому встроенное API от DataGrid часто «идет лесом».
Тогда проще всего использовать TemplateColumn и в нем прописывать триггеры, включающие инпуты редактирования, напр., когда строка выделена.
А работа с TemplateColumn что в DataGrid, что в ListView практически одинакова.

Так что мне кажется более уместным было в сравнение добавить именно ListView.
Получается достаточно дорого для разработки в ListView поддерживать редактирование шаблонами…
Хотя если в гриде все колонки шаблонные, то разница по разработке не сильно большая.

Надо пробовать, на сколько это может поднять производительность.
Я попробовал вместо грида в тесте использовать с ListView с GridView в нем. Без дополнительных темплейтов редактирования. Написать пример получилось быстро.

Но вот работал он ничуть не быстрее обычного грида WPF, FPS на скроллинге был ровно такой же…
В примере для WPF были включены EnableRowVirtualization=«True» EnableColumnVirtualization=«True»
Можете попробовать запустить примеры и счетчик, если отпишетесь тут с результатами и названием вашего процессора — будет полезно. Если сможете заставить их работать быстрее — будет еще полезнее.
Почему Qt такой древний? И почему бы не попробовать то-же самое на QML?
Qt использовался тот который оказался под рукой (5.2.1 вышел в 2014 году).
Вполне возможно более свежие Qt покажут результат лучше.
Если выложите пример на QML или результаты этого же теста собранного под более свежим Qt — будет очень полезно.
Как я понимаю FLTK гонит через OpenGL?
В FLTK неплохо интегрирована поддержка OpenGL, и некоторые контролы с префиксом Fl_Gl_ рендерятся через OpenGL, однако на сколько я понял, многие другие контролы, рендерятся стандартными средствами системы (Windows, Linux или MacOS)
А где MFC? Без него сравнение не будет полным! %)
Проблема в том, что на сколько мне известно в MFC нету контрола грид. (Например CListView это никак не грид)
Сравнивать же сторонние, и зачастую платные, контролы для MFC — наряду со стандартными контролами для других библиотек выглядит очень неравноценным сравнением.
Если там есть колонки, то очень даже уместно (по крайней мере в кейсе с неиспользуемой сортировкой и фильтрацией), которые в WPF, например, лучше выносить наружу.
В CListView не хватает возможности стандартного редактирования ячеек, там, на сколько мне известно, можно редактировать только первую колонку, это существенно сужает его применение для задач представления данных, где данные нужно еще и редактировать.
Да и в целом CListView плохо умеет работать с ячейками отдельно т.е. для него есть «первая» ячейка, а есть остальные. Конечно бывает этого и хватает.
Иными словами, на гриде можно решать практический любую задачу представления и редактирования табличных данных, а на ListView только часть этих задач, из-за меньшей универсальности CListView был выбран именно грид для тестов.

( и конечно если сравнивать листы, то их надо сравнивать уже с листами, а это совсем другое сравнение)
Понятно… Тогда да.
А в WPF ListView можно снабдить колонками с помощью GridView и для редактирования данных можно использовать TemplatedColumn. С DataGrid часто приходится дизайнить ячейки, потому его встроенная фича редактирования часто оказывается не востребованной.
Sign up to leave a comment.

Articles