From 818c544d6be0daf399ad69222b196e75e6b54505 Mon Sep 17 00:00:00 2001 From: Morten Johan Sorvig Date: Thu, 13 Dec 2012 14:54:47 +0100 Subject: Cache accessibility plugins. Profiling shows that the cost of QAcccessible:: queryAccessibleInterface is dominated by plugin loading. (json parsing etc.) Cache QAccessiblePlugin per class. Also cache the fact that no plugin is found for a certain class. This speeds up the average queryAccessibleInterface call by a factor of 10X Change-Id: Iab6d052dec499a2203d1dcc4672a8a543b279239 Reviewed-by: Frederik Gladhorn --- src/gui/accessible/qaccessible.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src/gui') diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index f55037c37a..28a3afbbf0 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -51,6 +51,7 @@ #include #include +#include #include QT_BEGIN_NAMESPACE @@ -430,6 +431,8 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, #endif Q_GLOBAL_STATIC(QList, qAccessibleFactories) +typedef QHash QAccessiblePluginsHash; +Q_GLOBAL_STATIC(QAccessiblePluginsHash, qAccessiblePlugins); QAccessible::UpdateHandler QAccessible::updateHandler = 0; QAccessible::RootObjectHandler QAccessible::rootObjectHandler = 0; @@ -580,9 +583,13 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) if (!object) return 0; + // Create a QAccessibleInterface for the object class. Start by the most + // derived class and walk up the class hierarchy. const QMetaObject *mo = object->metaObject(); while (mo) { const QString cn = QLatin1String(mo->className()); + + // Check if the class has a InterfaceFactory installed. for (int i = qAccessibleFactories()->count(); i > 0; --i) { InterfaceFactory factory = qAccessibleFactories()->at(i - 1); if (QAccessibleInterface *iface = factory(cn, object)) @@ -590,8 +597,21 @@ QAccessibleInterface *QAccessible::queryAccessibleInterface(QObject *object) } #ifndef QT_NO_ACCESSIBILITY #ifndef QT_NO_LIBRARY - if (QAccessibleInterface * iface = qLoadPlugin1(loader(), cn, object)) - return iface; + // Find a QAccessiblePlugin (factory) for the class name. If there's + // no entry in the cache try to create it using the plugin loader. + if (!qAccessiblePlugins()->contains(cn)) { + QAccessiblePlugin *factory = 0; // 0 means "no plugin found". This is cached as well. + const int index = loader()->indexOf(cn); + if (index != -1) + factory = qobject_cast(loader()->instance(index)); + qAccessiblePlugins()->insert(cn, factory); + } + + // At this point the cache should contain a valid factory pointer or 0: + Q_ASSERT(qAccessiblePlugins()->contains(cn)); + QAccessiblePlugin *factory = qAccessiblePlugins()->value(cn); + if (factory) + return factory->create(cn, object); #endif #endif mo = mo->superClass(); -- cgit v1.2.3