Commit 4bfe8804 authored by Richard Braakman's avatar Richard Braakman

[performance] Avoid resolving addresses multiple times

Parts of commhistory (GroupManager) will send a stream of
resolve requests with many duplicates. This used to be
tolerable because requests were handled slowly in the
event loop, but now that they have higher priority it has
become a problem.

I went for the simple solution of ignoring requests that
are identical to still-active requests (same uids, same
listener, same requireComplete flag). It's not optimal (we
could combine more requests into the same backend query if we
tried), but it solves the problem without adding a lot of
bookkeeping.
parent 1a2eec1c
...@@ -691,6 +691,15 @@ void SeasideCache::unregisterResolveListener(ResolveListener *listener) ...@@ -691,6 +691,15 @@ void SeasideCache::unregisterResolveListener(ResolveListener *listener)
++it3; ++it3;
} }
} }
QSet<ResolveData>::iterator it4 = instancePtr->m_pendingResolve.begin();
while (it4 != instancePtr->m_pendingResolve.end()) {
if (it4->listener == listener) {
it4 = instancePtr->m_pendingResolve.erase(it4);
} else {
++it4;
}
}
} }
void SeasideCache::setNameGrouper(SeasideNameGrouper *grouper) void SeasideCache::setNameGrouper(SeasideNameGrouper *grouper)
...@@ -2719,6 +2728,7 @@ void SeasideCache::addressRequestStateChanged(QContactAbstractRequest::State sta ...@@ -2719,6 +2728,7 @@ void SeasideCache::addressRequestStateChanged(QContactAbstractRequest::State sta
} }
data.listener->addressResolved(data.first, data.second, item); data.listener->addressResolved(data.first, data.second, item);
delete it.key(); delete it.key();
m_pendingResolve.remove(data);
m_resolveAddresses.erase(it); m_resolveAddresses.erase(it);
} }
...@@ -3090,6 +3100,10 @@ void SeasideCache::resolveAddress(ResolveListener *listener, const QString &firs ...@@ -3090,6 +3100,10 @@ void SeasideCache::resolveAddress(ResolveListener *listener, const QString &firs
data.requireComplete = requireComplete; data.requireComplete = requireComplete;
data.listener = listener; data.listener = listener;
// filter out duplicate requests
if (m_pendingResolve.find(data) != m_pendingResolve.end())
return;
// Is this address a known-unknown? // Is this address a known-unknown?
bool knownUnknown = false; bool knownUnknown = false;
QList<ResolveData>::const_iterator it = instancePtr->m_unknownAddresses.constBegin(), end = m_unknownAddresses.constEnd(); QList<ResolveData>::const_iterator it = instancePtr->m_unknownAddresses.constBegin(), end = m_unknownAddresses.constEnd();
...@@ -3138,6 +3152,7 @@ void SeasideCache::resolveAddress(ResolveListener *listener, const QString &firs ...@@ -3138,6 +3152,7 @@ void SeasideCache::resolveAddress(ResolveListener *listener, const QString &firs
connect(request, SIGNAL(stateChanged(QContactAbstractRequest::State)), connect(request, SIGNAL(stateChanged(QContactAbstractRequest::State)),
this, SLOT(addressRequestStateChanged(QContactAbstractRequest::State))); this, SLOT(addressRequestStateChanged(QContactAbstractRequest::State)));
m_resolveAddresses[request] = data; m_resolveAddresses[request] = data;
m_pendingResolve.insert(data);
request->start(); request->start();
} }
} }
...@@ -3205,5 +3220,27 @@ QContactRelationship SeasideCache::makeRelationship(const QString &type, const Q ...@@ -3205,5 +3220,27 @@ QContactRelationship SeasideCache::makeRelationship(const QString &type, const Q
return makeRelationship(type, contact1.id(), contact2.id()); return makeRelationship(type, contact1.id(), contact2.id());
} }
bool operator==(const SeasideCache::ResolveData &lhs, const SeasideCache::ResolveData &rhs)
{
// .listener and .requireComplete first because they are the cheapest comparisons
// then .second before .first because .second is most likely to be unequal
// .compare is derived from first and second so it does not need to be checked
return lhs.listener == rhs.listener
&& lhs.requireComplete == rhs.requireComplete
&& lhs.second == rhs.second
&& lhs.first == rhs.first;
}
uint qHash(const SeasideCache::ResolveData &key, uint seed)
{
uint h1 = qHash(key.first, seed);
uint h2 = qHash(key.second, seed);
uint h3 = key.requireComplete;
uint h4 = qHash(key.listener, seed);
// Don't xor with seed here because h4 already did that
return h1 ^ h2 ^ h3 ^ h4;
}
// Instantiate the contact ID functions for qtcontacts-sqlite // Instantiate the contact ID functions for qtcontacts-sqlite
#include <qtcontacts-extensions_impl.h> #include <qtcontacts-extensions_impl.h>
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include <QContactIdFetchRequest> #include <QContactIdFetchRequest>
#include <QBasicTimer> #include <QBasicTimer>
#include <QHash>
#include <QSet> #include <QSet>
#include <QElapsedTimer> #include <QElapsedTimer>
...@@ -469,11 +470,12 @@ private: ...@@ -469,11 +470,12 @@ private:
struct ResolveData { struct ResolveData {
QString first; QString first;
QString second; QString second;
QString compare; QString compare; // only used in m_unknownAddresses
bool requireComplete; bool requireComplete;
ResolveListener *listener; ResolveListener *listener;
}; };
QHash<QContactFetchRequest *, ResolveData> m_resolveAddresses; QHash<QContactFetchRequest *, ResolveData> m_resolveAddresses;
QSet<ResolveData> m_pendingResolve; // these have active requests already
QList<ResolveData> m_unknownResolveAddresses; QList<ResolveData> m_unknownResolveAddresses;
QList<ResolveData> m_unknownAddresses; QList<ResolveData> m_unknownAddresses;
QSet<QString> m_resolvedPhoneNumbers; QSet<QString> m_resolvedPhoneNumbers;
...@@ -484,6 +486,12 @@ private: ...@@ -484,6 +486,12 @@ private:
static SeasideCache *instancePtr; static SeasideCache *instancePtr;
static int contactNameGroupCount; static int contactNameGroupCount;
static QStringList allContactNameGroups; static QStringList allContactNameGroups;
friend bool operator==(const SeasideCache::ResolveData &lhs, const SeasideCache::ResolveData &rhs);
friend uint qHash(const SeasideCache::ResolveData &key, uint seed);
}; };
bool operator==(const SeasideCache::ResolveData &lhs, const SeasideCache::ResolveData &rhs);
uint qHash(const SeasideCache::ResolveData &key, uint seed = 0);
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment