Skip to content
This repository has been archived by the owner on Sep 4, 2021. It is now read-only.

Commit

Permalink
[performance] Avoid resolving addresses multiple times
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
amtep committed Feb 12, 2015
1 parent 1a2eec1 commit 4bfe880
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
37 changes: 37 additions & 0 deletions src/seasidecache.cpp
Expand Up @@ -691,6 +691,15 @@ void SeasideCache::unregisterResolveListener(ResolveListener *listener)
++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)
Expand Down Expand Up @@ -2719,6 +2728,7 @@ void SeasideCache::addressRequestStateChanged(QContactAbstractRequest::State sta
}
data.listener->addressResolved(data.first, data.second, item);
delete it.key();
m_pendingResolve.remove(data);
m_resolveAddresses.erase(it);
}

Expand Down Expand Up @@ -3090,6 +3100,10 @@ void SeasideCache::resolveAddress(ResolveListener *listener, const QString &firs
data.requireComplete = requireComplete;
data.listener = listener;

// filter out duplicate requests
if (m_pendingResolve.find(data) != m_pendingResolve.end())
return;

// Is this address a known-unknown?
bool knownUnknown = false;
QList<ResolveData>::const_iterator it = instancePtr->m_unknownAddresses.constBegin(), end = m_unknownAddresses.constEnd();
Expand Down Expand Up @@ -3138,6 +3152,7 @@ void SeasideCache::resolveAddress(ResolveListener *listener, const QString &firs
connect(request, SIGNAL(stateChanged(QContactAbstractRequest::State)),
this, SLOT(addressRequestStateChanged(QContactAbstractRequest::State)));
m_resolveAddresses[request] = data;
m_pendingResolve.insert(data);
request->start();
}
}
Expand Down Expand Up @@ -3205,5 +3220,27 @@ QContactRelationship SeasideCache::makeRelationship(const QString &type, const Q
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
#include <qtcontacts-extensions_impl.h>
10 changes: 9 additions & 1 deletion src/seasidecache.h
Expand Up @@ -52,6 +52,7 @@
#include <QContactIdFetchRequest>

#include <QBasicTimer>
#include <QHash>
#include <QSet>

#include <QElapsedTimer>
Expand Down Expand Up @@ -469,11 +470,12 @@ private slots:
struct ResolveData {
QString first;
QString second;
QString compare;
QString compare; // only used in m_unknownAddresses
bool requireComplete;
ResolveListener *listener;
};
QHash<QContactFetchRequest *, ResolveData> m_resolveAddresses;
QSet<ResolveData> m_pendingResolve; // these have active requests already
QList<ResolveData> m_unknownResolveAddresses;
QList<ResolveData> m_unknownAddresses;
QSet<QString> m_resolvedPhoneNumbers;
Expand All @@ -484,6 +486,12 @@ private slots:
static SeasideCache *instancePtr;
static int contactNameGroupCount;
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

0 comments on commit 4bfe880

Please sign in to comment.