Fix QGraphicsScene::update() performance
A previous fix has caused a performance degradation while adding a check for avoiding adding duplicated rectangles to the update list. This patch fixes it by using a std::set instead of a QList, avoiding duplication while using an O(log N) operation, instead of the O(N) used before. Fixes: QTBUG-77952 Change-Id: Ifa9fbf110e0bad60ee02a42d91281981fd98ceab Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
014d7ac654
commit
31012df705
@ -386,7 +386,15 @@ void QGraphicsScenePrivate::_q_emitUpdated()
|
|||||||
|
|
||||||
// Notify the changes to anybody interested.
|
// Notify the changes to anybody interested.
|
||||||
QList<QRectF> oldUpdatedRects;
|
QList<QRectF> oldUpdatedRects;
|
||||||
oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects;
|
if (updateAll) {
|
||||||
|
oldUpdatedRects << q->sceneRect();
|
||||||
|
} else {
|
||||||
|
// Switch to a ranged constructor in Qt 6...
|
||||||
|
oldUpdatedRects.reserve(int(updatedRects.size()));
|
||||||
|
std::copy(updatedRects.cbegin(), updatedRects.cend(),
|
||||||
|
std::back_inserter(oldUpdatedRects));
|
||||||
|
}
|
||||||
|
|
||||||
updateAll = false;
|
updateAll = false;
|
||||||
updatedRects.clear();
|
updatedRects.clear();
|
||||||
emit q->changed(oldUpdatedRects);
|
emit q->changed(oldUpdatedRects);
|
||||||
@ -3219,8 +3227,7 @@ void QGraphicsScene::update(const QRectF &rect)
|
|||||||
view->d_func()->updateRectF(rect);
|
view->d_func()->updateRectF(rect);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!d->updatedRects.contains(rect))
|
d->updatedRects.insert(rect);
|
||||||
d->updatedRects << rect;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,9 @@
|
|||||||
#include <QtWidgets/qstyle.h>
|
#include <QtWidgets/qstyle.h>
|
||||||
#include <QtWidgets/qstyleoption.h>
|
#include <QtWidgets/qstyleoption.h>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
QT_REQUIRE_CONFIG(graphicsview);
|
QT_REQUIRE_CONFIG(graphicsview);
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -122,7 +125,19 @@ public:
|
|||||||
QRectF growingItemsBoundingRect;
|
QRectF growingItemsBoundingRect;
|
||||||
|
|
||||||
void _q_emitUpdated();
|
void _q_emitUpdated();
|
||||||
QList<QRectF> updatedRects;
|
|
||||||
|
struct UpdatedRectsCmp
|
||||||
|
{
|
||||||
|
bool operator() (const QRectF &a, const QRectF &b) const noexcept
|
||||||
|
{
|
||||||
|
return std::make_tuple(a.y(), a.x(), a.height(), a.width())
|
||||||
|
< std::make_tuple(b.y(), b.x(), b.height(), b.width());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// std::set was used here instead of std::unordered_set due to requiring only a comparator and
|
||||||
|
// showing equivalent performance in empirical measurements within the ranges of interest...
|
||||||
|
std::set<QRectF, UpdatedRectsCmp> updatedRects;
|
||||||
|
|
||||||
QPainterPath selectionArea;
|
QPainterPath selectionArea;
|
||||||
int selectionChanging;
|
int selectionChanging;
|
||||||
|
@ -3685,8 +3685,6 @@ void tst_QGraphicsScene::changedSignal()
|
|||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
QCOMPARE(cl.changes.size(), 2);
|
QCOMPARE(cl.changes.size(), 2);
|
||||||
QCOMPARE(cl.changes.at(1).size(), 2);
|
QCOMPARE(cl.changes.at(1).size(), 2);
|
||||||
QCOMPARE(cl.changes.at(1).first(), QRectF(0, 0, 10, 10));
|
|
||||||
QCOMPARE(cl.changes.at(1).last(), QRectF(20, 0, 10, 10));
|
|
||||||
|
|
||||||
QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
|
QCOMPARE(scene.sceneRect(), QRectF(0, 0, 30, 10));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user