Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: sh123 от Март 10, 2009, 13:06



Название: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 10, 2009, 13:06
Добрый день, ALL!

У меня сложилась следующая ситуация:

1. Имеется QGraphicsView в котором находится большое количество элементов наследованных от QGraphicsItem (~10000), объекты статические их положение не изменяется, объекты не пересекаются.

2. В текущем viewport-е производится анимация объектов, для каждого элемента по таймеру вызывается QGraphicsItem::update

Проблема:

При вызове QGraphicsItem::update(), происходит ужасная потеря производительности (проц на 90%), похоже что QGraphicsView\QGraphicsScene проивоздит обход всех элементов при этом для каждого вызывает boundingRect().

Имеется ли какая-то возможности оптимизировать данное решение, или может у кого-то есть идеи по этому поводу. Заранее благодарен!


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 13:15
Самому определять видимые итемы и обновлять только их.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 10, 2009, 13:26
В данный момент update() вызывается только для итемов находящихся в видимой области, но QGraphicsView обходит все итемы так как я вижу вызовы к boundingRect() что вызывает падение производительности.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 13:30
В данный момент update() вызывается только для итемов находящихся в видимой области, но QGraphicsView обходит все итемы так как я вижу вызовы к boundingRect() что вызывает падение производительности.
Конечно обходит, ему же для отрисовки нужно знать, видим ли итем или нет.
Что у тебя в boundingRect()? Может там стоит оптимизировать?


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 10, 2009, 13:35
В boundingRect() пробовал даже возвращать просто фиксированный размер без всяких расчётов, помогло процентов на 30 только. Может есть какой-то способ заставить QGraphicsView не обходить все элементы.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 13:37
В boundingRect() пробовал даже возвращать просто фиксированный размер без всяких расчётов, помогло процентов на 30 только. Может есть какой-то способ заставить QGraphicsView не обходить все элементы.
А демонстрашка из Qt 40000 Chip у тебя как работает? Что с производительностью?


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 10, 2009, 13:47
Демка работает приемлимо без тормозов.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 13:49
так как я вижу вызовы к boundingRect() что вызывает падение производительности.
А ты как это видишь? Используешь qDebug?


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 10, 2009, 13:51
С выводом на консоль ещё сильнее тормозит :) само собой.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 13:51
Демка работает приемлимо без тормозов.
Так может это ты что-то делаешь не так?
Покажи код.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 14:17
Обрати еще внимание на void QGraphicsView::setViewportUpdateMode ( ViewportUpdateMode mode ).


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 10, 2009, 14:34
При оптимизации boundingRect() удалось добиться примерно 4-х кратного увеличения производительности, setViewPortUpdateMode() не вносит ощутимых изменений. По-видимому, в кутишном примере тормоза не заметны, как update() вызывается только при наведении юзером мыши на элемент, в моём случае периодичность таймера 100 миллисекунд. Странно, что qt тупо не обновляет элементы а обходит все пытаясь понять видимы они или нет и тд, почему нельзя просто обновить тот один элемент, на который я указал?


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 14:49
Странно, что qt тупо не обновляет элементы а обходит все пытаясь понять видимы они или нет и тд, почему нельзя просто обновить тот один элемент, на который я указал?
Подожди на Qt пинять, покажи свой код.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BaltikS от Март 10, 2009, 14:57
Чудеса какие-то.... Может в paintEvente что-то нахимичено?


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 10, 2009, 22:41
Вот создал что-то похожее на основе chip из примеров qt. Грузит проц на 100 процентов или может ли быть что проблема в graphicsView->items(b_rect)? Может быть я столкнулся с проблемой описанной тут:

http://lists.trolltech.com/qt4-preview-feedback/2006-09/thread00014-0.html


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 10, 2009, 22:53
Вот создал что-то похожее на основе chip из примеров qt. Грузит проц на 100 процентов. Может ли быть что проблема в graphicsView->items(b_rect)?
IMHO слот updateVisibleItems() выполняется за время более чем 100 мс. Т.е. сработал таймер, запустился слот обновления, отработал и таймер его тут же запустил вновь.
update() выполняется для всех итемов, а не только для видимых.
Программа делает ровно то что написано.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 11, 2009, 00:19
Также добавил второй немного изменённый пример в котором вместо текста просто отображается 20000 прямоугольников, причём все текущие видимые элементы кэшируются, так что graphicsView->items не вызывается. Данный пример стабильно грузит проц на 90-100 процентов.



Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 11, 2009, 00:25
Вот создал что-то похожее на основе chip из примеров qt. Грузит проц на 100 процентов. Может ли быть что проблема в graphicsView->items(b_rect)?
IMHO слот updateVisibleItems() выполняется за время более чем 100 мс. Т.е. сработал таймер, запустился слот обновления, отработал и таймер его тут же запустил вновь.
update() выполняется для всех итемов, а не только для видимых.
Программа делает ровно то что написано.

Так в этом то и проблема, что 100 миллисекунд недостаточно чтобы обновить видимые элементы или нет? У меня ~10 видимых квадратов (закэшеных во втором примере) и я говорю кути, чтобы она их обновила и просто чтобы обновить их у кути уходит больше 100 миллисекунд, что очень много или я чего-то не понимаю? Добавлю лишь, что возможно мне нужен аналог QWidget::repaint() для итемов, так как они не меняют своего положения и размера, необходимо просто перерисовать те 10 видимых элементов находящихся в текущем viewport.




Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 11, 2009, 11:41
Добавь в настройку QGraphicsView еще эти строки:
Код
C++ (Qt)
view->setOptimizationFlags( QGraphicsView::DontClipPainter  | QGraphicsView::DontSavePainterState | QGraphicsView::DontAdjustForAntialiasing );
view->setViewportUpdateMode( QGraphicsView::BoundingRectViewportUpdate );
 
Qt очень многое берет на себя, возможно часть функционала тебе не нужна - выключи.
Не забывай, что вся отрисовка проходит через матрицы трансформаций.
Также имеет большое значение, суммарный объем области обновления, т.е. если будет обновляться один итем который занимает все окно, это будет медленней, чем обновить десяток 20x20.

Добавленные строки у меня на машине уменьшили нагрузку процессора в двое.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 11, 2009, 13:07
Спасибо за информацию, попробую. Еще возникла пара вопросов, некоторые из флагов недоступны в ранних версиях qt4, как быть в этом случае? И возможно ли каким либо образом инициировать репаинт итема, без его uрdate из моего кода. Любые идеи в принципе подойдут, даже самые извращенные :) главное добиться как можно меньшей нагрузки на проц. Заранее благодарен!


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: BRE от Март 11, 2009, 13:18
Спасибо за информацию, попробую. Еще возникла пара вопросов, некоторые из флагов недоступны в ранних версиях qt4, как быть в этом случае? И возможно ли каким либо образом инициировать репаинт итема, без его uрdate из моего кода. Любые идеи в принципе подойдут, даже самые извращенные :) главное добиться как можно меньшей нагрузки на проц. Заранее благодарен!
Как мне кажется, тут нужно исходить из того, какой тебе необходим функционал от Qt?
Будут повороты, масштабирование? Необходимость выбора итемов мышкой, drag&drop?
Может проще будет на pixmap рисовать.


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 11, 2009, 15:00
Спасибо за информацию, попробую. Еще возникла пара вопросов, некоторые из флагов недоступны в ранних версиях qt4, как быть в этом случае? И возможно ли каким либо образом инициировать репаинт итема, без его uрdate из моего кода. Любые идеи в принципе подойдут, даже самые извращенные :) главное добиться как можно меньшей нагрузки на проц. Заранее благодарен!
Как мне кажется, тут нужно исходить из того, какой тебе необходим функционал от Qt?
Будут повороты, масштабирование? Необходимость выбора итемов мышкой, drag&drop?
Может проще будет на pixmap рисовать.


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


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: Khs от Март 11, 2009, 15:03
кстати, мне тоже интересно какие флаги оптимизации View и может самих айтемов желательны в таком случае :) (в моем случае для разработки карты дорог, городов и тп.)


Название: Re: QGraphicsView и QGraphicsItem::update оптимизация
Отправлено: sh123 от Март 11, 2009, 22:05
Эти флаги роли не играют также 100 процентов
view->setOptimizationFlags( QGraphicsView::DontClipPainter  | QGraphicsView::DontSavePainterState | QGraphicsView::DontAdjustForAntialiasing );

А вот этот флаг снизил нагрузку в 4 раза
view->setViewportUpdateMode( QGraphicsView::BoundingRectViewportUpdate );

Проблема в том что последний доступен только начиная с 4.4 кути :( мне необходимо чтобы апликачка работала на 4.3 тоже. Похоже придётся вообще отказаться от QGraphicsView.