Привет всем. Решил написать свой ListView, потому что стандартный задолбал своими глюками при нестандартной отрисовке, а в .NET для того чтобы написать свою отрисовку для ListView надо WndProc переопределять (кроме того тут присутствует чисто спортивный инетерес это сделать). Решил ваять на C# под .NET 1.1. Все отлично кроме ситуации когда за раз надо отрисовать много элементов, напирмер, в разрешении 1600x1200 если развернуть окно на весь экран, то в рабочую область помещаеться около 3000 элементов и процесс перерисовки жутко тормозит. Пробовал оптимизировать: Рисовать все на Bitmap, а потом в OnPaint копировать с него в окно, а на битмапе все перерисовывать при изменении самих элементов. Это кноечно помогло, но не решило проблему полностью, при изменении размеров контрола, меняеться порядок элементов, размещенных в рабочей области и соответственно в OnResize надо перерисовать bitmap, а потом перенести его еще на контрол, и тормоза снова появляються, причем еще большие, так как в этом случае имеет место копирование достаточно большого битмапа ( разрешение близкое к 1600х1200 ).
Как сделать его по человечески ума не приложу, но как — то можно ибо виндовый компонент нормально справляеться с такой ситуацией.
Пробовал сделать его на WinAPI с использованием голого C++ и результат получился конечно немного пошустрее, но не настолько, чтобы решить проблему, тут надо именно алгоритмически ее решать.
Посмотри внимательно описание метода Control.SetStyle() — должно помочь с буферизацией
А если очень хочеться что-то кэшировать, то попробуй кэшировать содержимое ячеек (в виде картинки или чего ещё, не важно). У себя дома я выжал из gdi+ в 1280х1024 около 15 кадров в секунду, при заполнении экрана квадратиками 32х32 на атлоне 2000+, такчто если ячейки будут в кэше, будет рисоваться быстро.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Visor2004, Вы писали:
А>[skipped]
А>Посмотри внимательно описание метода Control.SetStyle() — должно помочь с буферизацией А>А если очень хочеться что-то кэшировать, то попробуй кэшировать содержимое ячеек (в виде картинки или чего ещё, не важно). У себя дома я выжал А>из gdi+ в 1280х1024 около 15 кадров в секунду, при заполнении экрана квадратиками 32х32 на атлоне 2000+, такчто если ячейки будут в кэше, А>будет рисоваться быстро.
Буферизация — это конечно здорово, изображение не мерцает, но быстродействия оно не добавляет. А вот про кэширование элементов — это интересно. Я думал над этим. В голову пришла такая мысль: Можно попробовать посчитать сколько элементов будет видимо в рабочей области при максимальном размере контрола на данном разрешении, потом создать соответствующее количество битмапов и рисовать элементы на нем, а при изменении размера, когда положение элементов будет "тасоваться" просто забирать битмапы у элементов которые стали невилимыми и переназначать их видимым элементам (так же поступать и при скроллировании элемента).
Тут тогда у меня другой вопрос, как GDI+ отреагирует на создание 3000 битмапов? Не приведет-ли это к каким-нить негативным последствиям? Типа нехватки ресурсов или чего-то еще такого....
Если тебе не сложно, можешь исходник своего алгоритма дать на изучение, если не весь, то хоть ключевые моменты.
Здравствуйте, alku, Вы писали:
A>Здравствуйте, Visor2004, Вы писали:
V>>Здравствуйте, Аноним, Вы писали:
А>>>Здравствуйте, Visor2004, Вы писали:
A>[skipped]
A>минимизни количество перерисовки, т.е. обращай внимание на A>- Graphics.Clip
A>BeginUpdate/EndUpdate == LockDrawing/UnlockDrawing ==>
A>WindowsAPI.SendMessage( Handle, ( int )Msg.WM_SETREDRAW, 0, 0 );
A>оптимизни алогоритм отрисовки айтемов, т.е. прорисовки бак-граундов сведи к перерисовки только Clip пространств... и т.д.
Это все там уже реализовано и много чего еще, но суть в том, что стандарные подходы к оптимизации рисования тут не подойдут, тут надо придумать, другой подход, основанный на кэшировании мне кажеться.
Здравствуйте, Visor2004, Вы писали:
V>Пробовал оптимизировать <...>
А померить, что именно тормозит пробовал?
Берешь профайлер, смотришь, где тратится максимальное количество времени и дальше думаешь. А оптимизировать на основе интуиции — верный способ потратить кучу времени и не добиться результата.
Здравствуйте, orangy, Вы писали:
O>Здравствуйте, Visor2004, Вы писали:
V>>Пробовал оптимизировать <...>
O>А померить, что именно тормозит пробовал? O>Берешь профайлер, смотришь, где тратится максимальное количество времени и дальше думаешь. А оптимизировать на основе интуиции — верный способ потратить кучу времени и не добиться результата.
Это инетересно, а что под .NET есть и такое, я помню под Win32 с этим были такие проблемы, что я уже приучился обходиться без них. Порекомендуйте какой-нить хороший.....
Здравствуйте, Visor2004, Вы писали:
V>>>Пробовал оптимизировать <...> O>>А померить, что именно тормозит пробовал? O>>Берешь профайлер, смотришь, где тратится максимальное количество времени и дальше думаешь. А оптимизировать на основе интуиции — верный способ потратить кучу времени и не добиться результата.
V>Это инетересно, а что под .NET есть и такое, я помню под Win32 с этим были такие проблемы, что я уже приучился обходиться без них. Порекомендуйте какой-нить хороший.....
Под Win32 есть отличные профайлеры, например Intel VTune. Для дотнет можно посмотреть JetBrains dotTrace, хотя он еще в первой версии и сыроват. Для отслеживания утечек памяти рекомендую .NET Memory Profiler. В комплекте они оба два дают поразительный результат. Ждем второй версии dotTrace и может быть будет нам счастье...
ЗЫ: Ни с одним из продуктов я не состою в родственных отношениях
A>>оптимизни алогоритм отрисовки айтемов, т.е. прорисовки бак-граундов сведи к перерисовки только Clip пространств... и т.д.
V>Это все там уже реализовано и много чего еще, но суть в том, что стандарные подходы к оптимизации рисования тут не подойдут, тут надо придумать, другой подход, основанный на кэшировании мне кажеться.
виндовый контрол во первых не использует хранение итемов в самом себе, а во-вторых сильно заточен под показывание файловой системы. под дотнетом 1.1 (без использования API) ты не добьешься такого быстродействия. в 2.0 уже есть поддержка "виртуальных" ListView, так что там это вполне осуществимо. особено, если использовать какой-нить unsafe, чтобы он данные не копировал лишний раз, а брал их как задумывалось, по указателю.
Здравствуйте, andreich78, Вы писали:
A>Здравствуйте, Visor2004, Вы писали:
A>>>оптимизни алогоритм отрисовки айтемов, т.е. прорисовки бак-граундов сведи к перерисовки только Clip пространств... и т.д.
V>>Это все там уже реализовано и много чего еще, но суть в том, что стандарные подходы к оптимизации рисования тут не подойдут, тут надо придумать, другой подход, основанный на кэшировании мне кажеться.
A>виндовый контрол во первых не использует хранение итемов в самом себе, а во-вторых сильно заточен под показывание файловой системы. под дотнетом 1.1 (без использования API) ты не добьешься такого быстродействия. в 2.0 уже есть поддержка "виртуальных" ListView, так что там это вполне осуществимо. особено, если использовать какой-нить unsafe, чтобы он данные не копировал лишний раз, а брал их как задумывалось, по указателю.
Что значит "Виртуальный" ListView. А на счет производительности, то я уже писал, что это алгоритмическая проблема, а не проблема инструментария. A>виндовый контрол во первых не использует хранение итемов в самом себе
А где же он хранит структуры, в кот. храниться указатель на строку, индекс иконы и указатель на данные пользователя. A>чтобы он данные не копировал лишний раз, а брал их как задумывалось, по указателю.
Никакие данные у меня не копируются, а берутся именно по указателю, по ссылке т.е.
Здравствуйте, Visor2004, Вы писали:
V>Здравствуйте, andreich78, Вы писали:
A>>Здравствуйте, Visor2004, Вы писали:
A>>>>оптимизни алогоритм отрисовки айтемов, т.е. прорисовки бак-граундов сведи к перерисовки только Clip пространств... и т.д.
V>>>Это все там уже реализовано и много чего еще, но суть в том, что стандарные подходы к оптимизации рисования тут не подойдут, тут надо придумать, другой подход, основанный на кэшировании мне кажеться.
A>>виндовый контрол во первых не использует хранение итемов в самом себе, а во-вторых сильно заточен под показывание файловой системы. под дотнетом 1.1 (без использования API) ты не добьешься такого быстродействия. в 2.0 уже есть поддержка "виртуальных" ListView, так что там это вполне осуществимо. особено, если использовать какой-нить unsafe, чтобы он данные не копировал лишний раз, а брал их как задумывалось, по указателю.
V> Что значит "Виртуальный" ListView. А на счет производительности, то я уже писал, что это алгоритмическая проблема, а не проблема инструментария. A>>виндовый контрол во первых не использует хранение итемов в самом себе V> А где же он хранит структуры, в кот. храниться указатель на строку, индекс иконы и указатель на данные пользователя. A>>чтобы он данные не копировал лишний раз, а брал их как задумывалось, по указателю. V> Никакие данные у меня не копируются, а берутся именно по указателю, по ссылке т.е.
виртуальными они (MS здесь описание в разделе "Virtual List-View Style") называют контролы, не хранящие отображаемые данные, контрол только дергает обработчика и получает все необходимые параметры (именно указатель на строку, индекс иконы и указатель на данные пользователя), обработчик тоже не дергается без особой надобности, что тоже увеличивает быстродействие. в 1.1 поддержка этого режима отсутствует — контрол содержит в коллекции все итемы, итемы содержат текст ноды, и при создании нод (не проверял, но сомневаюсь, чтобы было иначе) текст ноды копируется, а не передается по ссылке.
Здравствуйте, andreich78, Вы писали:
A>виртуальными они (MS здесь описание в разделе "Virtual List-View Style") называют контролы, не хранящие отображаемые данные, контрол только дергает обработчика и получает все необходимые параметры (именно указатель на строку, индекс иконы и указатель на данные пользователя), обработчик тоже не дергается без особой надобности, что тоже увеличивает быстродействие. в 1.1 поддержка этого режима отсутствует — контрол содержит в коллекции все итемы, итемы содержат текст ноды, и при создании нод (не проверял, но сомневаюсь, чтобы было иначе) текст ноды копируется, а не передается по ссылке.
Ага, понятно. Но непонятно как это сказываеться на быстродействии перерисовки элемента, я согласен, что это может замедлить работу по заполнению, перемещению элементов, но никак не их прорисовку. Потому что нет никакой разницы, как рисовать иконку по индексу, кот. мы получаем из обработчика, или из структуры...... То что вы пишите, конечно интересно, но решить проблему это не помогает.
К предыдущему сообщению: А "Виртуальный" режим работы предназначен скорее всего для того, что бы предоставить пользователю возможность самому контролировать расход ресурсов под итемы и вручную задавать их физическое местопопложение, например, еси их 2000000000, то их можно расположить в файле подкачки и т. д.
я торможу как обычно...
V>>Как сделать его по человечески ума не приложу, но как — то можно ибо виндовый компонент нормально справляеться с такой ситуацией.
он же не отрисовывает нестандартной? или я ошибаюсь?
Здравствуйте, andreich78, Вы писали:
A>Здравствуйте, Visor2004, Вы писали:
A>я торможу как обычно...
V>>>Как сделать его по человечески ума не приложу, но как — то можно ибо виндовый компонент нормально справляеться с такой ситуацией.
A>он же не отрисовывает нестандартной? или я ошибаюсь?
Не понял вопроса, если имееться ввиду поддерживает-ли стандартный ListView пользовательскую отрисовку элементов — то Да, поддерживает.
Здравствуйте, andreich78, Вы писали:
A>Здравствуйте, Visor2004, Вы писали:
A>я торможу как обычно...
V>>>Как сделать его по человечески ума не приложу, но как — то можно ибо виндовый компонент нормально справляеться с такой ситуацией.
A>он же не отрисовывает нестандартной? или я ошибаюсь?
Не понял вопроса, если имееться ввиду поддерживает-ли стандартный ListView пользовательскую отрисовку элементов — то Да, поддерживает.
Здравствуйте, Visor2004, Вы писали:
V>Здравствуйте, andreich78, Вы писали:
A>>Здравствуйте, Visor2004, Вы писали:
A>>я торможу как обычно...
V>>>>Как сделать его по человечески ума не приложу, но как — то можно ибо виндовый компонент нормально справляеться с такой ситуацией.
A>>он же не отрисовывает нестандартной? или я ошибаюсь?
V>Не понял вопроса, если имееться ввиду поддерживает-ли стандартный ListView пользовательскую отрисовку элементов — то Да, поддерживает.
имеется в виду тот случай, с которым сравнивается производительность — там точно отрисовка нестандартная?
Здравствуйте, andreich78, Вы писали:
A>Здравствуйте, Visor2004, Вы писали:
V>>Здравствуйте, andreich78, Вы писали:
A>>>Здравствуйте, Visor2004, Вы писали:
A>>>я торможу как обычно...
V>>>>>Как сделать его по человечески ума не приложу, но как — то можно ибо виндовый компонент нормально справляеться с такой ситуацией.
A>>>он же не отрисовывает нестандартной? или я ошибаюсь?
V>>Не понял вопроса, если имееться ввиду поддерживает-ли стандартный ListView пользовательскую отрисовку элементов — то Да, поддерживает.
A>имеется в виду тот случай, с которым сравнивается производительность — там точно отрисовка нестандартная?
Да, точно.Я думаю сделать кэш из битмапов, кот потом просто переносить на канву и динамически распределять его между всеми вилимыми в данный момент элементами, но никак не могу понятть как GDI+ отнесеться к созданию 3000 битмапов, не будет — ли это сильно много ресурсов отъедать?
Здравствуйте, Visor2004, Вы писали:
V>Здравствуйте, andreich78, Вы писали:
A>>Здравствуйте, Visor2004, Вы писали:
V>>>Здравствуйте, andreich78, Вы писали:
A>>>>Здравствуйте, Visor2004, Вы писали:
A>>>>я торможу как обычно...
V>>>>>>Как сделать его по человечески ума не приложу, но как — то можно ибо виндовый компонент нормально справляеться с такой ситуацией.
A>>>>он же не отрисовывает нестандартной? или я ошибаюсь?
V>>>Не понял вопроса, если имееться ввиду поддерживает-ли стандартный ListView пользовательскую отрисовку элементов — то Да, поддерживает.
A>>имеется в виду тот случай, с которым сравнивается производительность — там точно отрисовка нестандартная?
V>Да, точно.
а где это можно посмотреть?
V>Я думаю сделать кэш из битмапов, кот потом просто переносить на канву и динамически распределять его между всеми вилимыми в данный момент элементами, но никак не могу понятть как GDI+ отнесеться к созданию 3000 битмапов, не будет — ли это сильно много ресурсов отъедать?
битмапы — не будут, пока до экранных ресурсов не доберешься — больших проблем не будет. с памятью проблемы будут. даже чистой памяти на 8-х битную иконку 16 Х 16 потребуется 2кБ памяти 3000 штук по 2к = 6МБ. а с учетом того, что всё хозяйство лежит в управляемой куче и над каждой иконкой обертка в виде класса — думаю, форма только с одним контролом будет весить межков 20...
а если хранить только уникальные битмапы — то с тем же успехом можно использовать просто imagelist...
я потому и хочу посмотреть на пример, который не тормозит. гораздо ведь проще поковыряться в том,что есть, чем делать заново
Кинь ListView на форму и напиши свой обработчик функции рисования, например, в Delphi, в NET для этого писать много надо, создай там, например, 10000 элементов и тогда увилишь, что он не тормозит.
V>>Я думаю сделать кэш из битмапов, кот потом просто переносить на канву и динамически распределять его между всеми вилимыми в данный момент элементами, но никак не могу понятть как GDI+ отнесеться к созданию 3000 битмапов, не будет — ли это сильно много ресурсов отъедать?
A>битмапы — не будут, пока до экранных ресурсов не доберешься — больших проблем не будет. с памятью проблемы будут. даже чистой памяти на 8-х битную иконку 16 Х 16 потребуется 2кБ памяти 3000 штук по 2к = 6МБ. а с учетом того, что всё хозяйство лежит в управляемой куче и над каждой иконкой обертка в виде класса — думаю, форма только с одним контролом будет весить межков 20... A>а если хранить только уникальные битмапы — то с тем же успехом можно использовать просто imagelist...
A>я потому и хочу посмотреть на пример, который не тормозит. гораздо ведь проще поковыряться в том,что есть, чем делать заново
Я вот за память и говорю, bitmapы я хочу использовать для того, что бы на каждом битмапе рисовать изображение одного видимого итема, а не только его картинки. Про ImageList не понял еси честно, что имееться ввиду.
Здравствуйте, Visor2004, Вы писали:
V>>>Да, точно.
A>>а где это можно посмотреть?
V>Кинь ListView на форму и напиши свой обработчик функции рисования, например, в Delphi, в NET для этого писать много надо, создай там, например, 10000 элементов и тогда увилишь, что он не тормозит.
пнятна. я думал, ты под .NET видел нетормозящую отрисовку.
тормоза не из-за алгоритма, я тебя уверяю
попробуй спуститься на уровень ниже и рисовать без использования GDI+ эффект должен быть разительным.
Здравствуйте, andreich78, Вы писали:
A>Здравствуйте, Visor2004, Вы писали:
V>>>>Да, точно.
A>>>а где это можно посмотреть?
V>>Кинь ListView на форму и напиши свой обработчик функции рисования, например, в Delphi, в NET для этого писать много надо, создай там, например, 10000 элементов и тогда увилишь, что он не тормозит.
A>пнятна. я думал, ты под .NET видел нетормозящую отрисовку. A>тормоза не из-за алгоритма, я тебя уверяю A>попробуй спуститься на уровень ниже и рисовать без использования GDI+ эффект должен быть разительным.
Никакого разительного эффекта не наблюдается, я пробовал. В своем самом первом посте я говорил об этом.