diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-07-28 22:29:35 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-07-28 22:29:35 +0200 |
commit | a24bf3db83d81d7d7677a1f0f750f208d32998a8 (patch) | |
tree | 0d3fa9da24d706c2e6b03e8bf0fd74a434ae871f | |
parent | 683ee2ec1d198a9f19572e42d78fa0b9939d7f10 (diff) | |
download | sink-a24bf3db83d81d7d7677a1f0f750f208d32998a8.tar.gz sink-a24bf3db83d81d7d7677a1f0f750f208d32998a8.zip |
Avoid unnecessary Identifier conversions in performance ciritical code.
This fixes the performance regressions to a state where we are roughly
at the same performance as pre Identifier (but not any better either).
-rw-r--r-- | common/datastorequery.cpp | 14 | ||||
-rw-r--r-- | common/storage/entitystore.cpp | 12 | ||||
-rw-r--r-- | common/storage/entitystore.h | 4 | ||||
-rw-r--r-- | common/storage/key.cpp | 6 | ||||
-rw-r--r-- | common/storage/key.h | 2 | ||||
-rw-r--r-- | common/typeindex.cpp | 27 | ||||
-rw-r--r-- | common/typeindex.h | 2 |
7 files changed, 40 insertions, 27 deletions
diff --git a/common/datastorequery.cpp b/common/datastorequery.cpp index 52243da..43b4660 100644 --- a/common/datastorequery.cpp +++ b/common/datastorequery.cpp | |||
@@ -46,14 +46,10 @@ class Source : public FilterBase { | |||
46 | QVector<Identifier> mIncrementalIds; | 46 | QVector<Identifier> mIncrementalIds; |
47 | QVector<Identifier>::ConstIterator mIncrementalIt; | 47 | QVector<Identifier>::ConstIterator mIncrementalIt; |
48 | 48 | ||
49 | Source (const QVector<QByteArray> &ids, DataStoreQuery *store) | 49 | Source (const QVector<Identifier> &ids, DataStoreQuery *store) |
50 | : FilterBase(store), | 50 | : FilterBase(store), |
51 | mIds() | 51 | mIds(ids) |
52 | { | 52 | { |
53 | mIds.reserve(ids.size()); | ||
54 | for (const auto &id : ids) { | ||
55 | mIds.append(Identifier::fromDisplayByteArray(id)); | ||
56 | } | ||
57 | mIt = mIds.constBegin(); | 53 | mIt = mIds.constBegin(); |
58 | } | 54 | } |
59 | 55 | ||
@@ -614,7 +610,11 @@ void DataStoreQuery::setupQuery(const Sink::QueryBase &query_) | |||
614 | mSource = [&]() { | 610 | mSource = [&]() { |
615 | if (!query.ids().isEmpty()) { | 611 | if (!query.ids().isEmpty()) { |
616 | //We have a set of ids as a starting point | 612 | //We have a set of ids as a starting point |
617 | return Source::Ptr::create(query.ids().toVector(), this); | 613 | QVector<Identifier> ids; |
614 | for (const auto & id: query.ids()) { | ||
615 | ids.append(Identifier::fromDisplayByteArray(id)); | ||
616 | } | ||
617 | return Source::Ptr::create(ids, this); | ||
618 | } else { | 618 | } else { |
619 | QSet<QByteArrayList> appliedFilters; | 619 | QSet<QByteArrayList> appliedFilters; |
620 | auto resultSet = mStore.indexLookup(mType, query, appliedFilters, appliedSorting); | 620 | auto resultSet = mStore.indexLookup(mType, query, appliedFilters, appliedSorting); |
diff --git a/common/storage/entitystore.cpp b/common/storage/entitystore.cpp index 71690fe..1ba7c6c 100644 --- a/common/storage/entitystore.cpp +++ b/common/storage/entitystore.cpp | |||
@@ -426,19 +426,19 @@ bool EntityStore::cleanupRevisions(qint64 revision) | |||
426 | return cleanupIsNecessary; | 426 | return cleanupIsNecessary; |
427 | } | 427 | } |
428 | 428 | ||
429 | QVector<QByteArray> EntityStore::fullScan(const QByteArray &type) | 429 | QVector<Identifier> EntityStore::fullScan(const QByteArray &type) |
430 | { | 430 | { |
431 | SinkTraceCtx(d->logCtx) << "Looking for : " << type; | 431 | SinkTraceCtx(d->logCtx) << "Looking for : " << type; |
432 | if (!d->exists()) { | 432 | if (!d->exists()) { |
433 | SinkTraceCtx(d->logCtx) << "Database is not existing: " << type; | 433 | SinkTraceCtx(d->logCtx) << "Database is not existing: " << type; |
434 | return QVector<QByteArray>(); | 434 | return {}; |
435 | } | 435 | } |
436 | //The scan can return duplicate results if we have multiple revisions, so we use a set to deduplicate. | 436 | //The scan can return duplicate results if we have multiple revisions, so we use a set to deduplicate. |
437 | QSet<QByteArray> keys; | 437 | QSet<Identifier> keys; |
438 | DataStore::mainDatabase(d->getTransaction(), type) | 438 | DataStore::mainDatabase(d->getTransaction(), type) |
439 | .scan(QByteArray(), | 439 | .scan(QByteArray(), |
440 | [&](const QByteArray &key, const QByteArray &value) -> bool { | 440 | [&](const QByteArray &key, const QByteArray &value) -> bool { |
441 | const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier().toDisplayByteArray(); | 441 | const auto uid = Sink::Storage::Key::fromInternalByteArray(key).identifier(); |
442 | if (keys.contains(uid)) { | 442 | if (keys.contains(uid)) { |
443 | //Not something that should persist if the replay works, so we keep a message for now. | 443 | //Not something that should persist if the replay works, so we keep a message for now. |
444 | SinkTraceCtx(d->logCtx) << "Multiple revisions for key: " << key; | 444 | SinkTraceCtx(d->logCtx) << "Multiple revisions for key: " << key; |
@@ -452,11 +452,11 @@ QVector<QByteArray> EntityStore::fullScan(const QByteArray &type) | |||
452 | return keys.toList().toVector(); | 452 | return keys.toList().toVector(); |
453 | } | 453 | } |
454 | 454 | ||
455 | QVector<QByteArray> EntityStore::indexLookup(const QByteArray &type, const QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting) | 455 | QVector<Identifier> EntityStore::indexLookup(const QByteArray &type, const QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting) |
456 | { | 456 | { |
457 | if (!d->exists()) { | 457 | if (!d->exists()) { |
458 | SinkTraceCtx(d->logCtx) << "Database is not existing: " << type; | 458 | SinkTraceCtx(d->logCtx) << "Database is not existing: " << type; |
459 | return QVector<QByteArray>(); | 459 | return {}; |
460 | } | 460 | } |
461 | return d->typeIndex(type).query(query, appliedFilters, appliedSorting, d->getTransaction(), d->resourceContext.instanceId()); | 461 | return d->typeIndex(type).query(query, appliedFilters, appliedSorting, d->getTransaction(), d->resourceContext.instanceId()); |
462 | } | 462 | } |
diff --git a/common/storage/entitystore.h b/common/storage/entitystore.h index 619b884..7979798 100644 --- a/common/storage/entitystore.h +++ b/common/storage/entitystore.h | |||
@@ -57,8 +57,8 @@ public: | |||
57 | void abortTransaction(); | 57 | void abortTransaction(); |
58 | bool hasTransaction() const; | 58 | bool hasTransaction() const; |
59 | 59 | ||
60 | QVector<QByteArray> fullScan(const QByteArray &type); | 60 | QVector<Sink::Storage::Identifier> fullScan(const QByteArray &type); |
61 | QVector<QByteArray> indexLookup(const QByteArray &type, const QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting); | 61 | QVector<Sink::Storage::Identifier> indexLookup(const QByteArray &type, const QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting); |
62 | QVector<Sink::Storage::Identifier> indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value); | 62 | QVector<Sink::Storage::Identifier> indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value); |
63 | void indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value, const std::function<void(const QByteArray &uid)> &callback); | 63 | void indexLookup(const QByteArray &type, const QByteArray &property, const QVariant &value, const std::function<void(const QByteArray &uid)> &callback); |
64 | template<typename EntityType, typename PropertyType> | 64 | template<typename EntityType, typename PropertyType> |
diff --git a/common/storage/key.cpp b/common/storage/key.cpp index 23d7a6a..2327061 100644 --- a/common/storage/key.cpp +++ b/common/storage/key.cpp | |||
@@ -26,6 +26,12 @@ using Sink::Storage::Identifier; | |||
26 | using Sink::Storage::Key; | 26 | using Sink::Storage::Key; |
27 | using Sink::Storage::Revision; | 27 | using Sink::Storage::Revision; |
28 | 28 | ||
29 | |||
30 | uint Sink::Storage::qHash(const Sink::Storage::Identifier &identifier) | ||
31 | { | ||
32 | return qHash(identifier.toInternalByteArray()); | ||
33 | } | ||
34 | |||
29 | QDebug &operator<<(QDebug &dbg, const Identifier &id) | 35 | QDebug &operator<<(QDebug &dbg, const Identifier &id) |
30 | { | 36 | { |
31 | dbg << id.toDisplayString(); | 37 | dbg << id.toDisplayString(); |
diff --git a/common/storage/key.h b/common/storage/key.h index 211aea7..baabe38 100644 --- a/common/storage/key.h +++ b/common/storage/key.h | |||
@@ -119,6 +119,8 @@ private: | |||
119 | Revision rev; | 119 | Revision rev; |
120 | }; | 120 | }; |
121 | 121 | ||
122 | SINK_EXPORT uint qHash(const Sink::Storage::Identifier &); | ||
123 | |||
122 | } // namespace Storage | 124 | } // namespace Storage |
123 | } // namespace Sink | 125 | } // namespace Sink |
124 | 126 | ||
diff --git a/common/typeindex.cpp b/common/typeindex.cpp index 47512e8..646a60f 100644 --- a/common/typeindex.cpp +++ b/common/typeindex.cpp | |||
@@ -265,10 +265,10 @@ void TypeIndex::remove(const Identifier &identifier, const Sink::ApplicationDoma | |||
265 | } | 265 | } |
266 | } | 266 | } |
267 | 267 | ||
268 | static QVector<QByteArray> indexLookup(Index &index, QueryBase::Comparator filter, | 268 | static QVector<Identifier> indexLookup(Index &index, QueryBase::Comparator filter, |
269 | std::function<QByteArray(const QVariant &)> valueToKey = getByteArray) | 269 | std::function<QByteArray(const QVariant &)> valueToKey = getByteArray) |
270 | { | 270 | { |
271 | QVector<QByteArray> keys; | 271 | QVector<Identifier> keys; |
272 | QByteArrayList lookupKeys; | 272 | QByteArrayList lookupKeys; |
273 | if (filter.comparator == Query::Comparator::Equals) { | 273 | if (filter.comparator == Query::Comparator::Equals) { |
274 | lookupKeys << valueToKey(filter.value); | 274 | lookupKeys << valueToKey(filter.value); |
@@ -283,7 +283,7 @@ static QVector<QByteArray> indexLookup(Index &index, QueryBase::Comparator filte | |||
283 | for (const auto &lookupKey : lookupKeys) { | 283 | for (const auto &lookupKey : lookupKeys) { |
284 | index.lookup(lookupKey, | 284 | index.lookup(lookupKey, |
285 | [&](const QByteArray &value) { | 285 | [&](const QByteArray &value) { |
286 | keys << Identifier::fromInternalByteArray(value).toDisplayByteArray(); | 286 | keys << Identifier::fromInternalByteArray(value); |
287 | }, | 287 | }, |
288 | [lookupKey](const Index::Error &error) { | 288 | [lookupKey](const Index::Error &error) { |
289 | SinkWarning() << "Lookup error in index: " << error.message << lookupKey; | 289 | SinkWarning() << "Lookup error in index: " << error.message << lookupKey; |
@@ -293,7 +293,7 @@ static QVector<QByteArray> indexLookup(Index &index, QueryBase::Comparator filte | |||
293 | return keys; | 293 | return keys; |
294 | } | 294 | } |
295 | 295 | ||
296 | static QVector<QByteArray> sortedIndexLookup(Index &index, QueryBase::Comparator filter) | 296 | static QVector<Identifier> sortedIndexLookup(Index &index, QueryBase::Comparator filter) |
297 | { | 297 | { |
298 | if (filter.comparator == Query::Comparator::In || filter.comparator == Query::Comparator::Contains) { | 298 | if (filter.comparator == Query::Comparator::In || filter.comparator == Query::Comparator::Contains) { |
299 | SinkWarning() << "In and Contains comparison not supported on sorted indexes"; | 299 | SinkWarning() << "In and Contains comparison not supported on sorted indexes"; |
@@ -303,7 +303,7 @@ static QVector<QByteArray> sortedIndexLookup(Index &index, QueryBase::Comparator | |||
303 | return indexLookup(index, filter, toSortableByteArray); | 303 | return indexLookup(index, filter, toSortableByteArray); |
304 | } | 304 | } |
305 | 305 | ||
306 | QVector<QByteArray> keys; | 306 | QVector<Identifier> keys; |
307 | 307 | ||
308 | QByteArray lowerBound, upperBound; | 308 | QByteArray lowerBound, upperBound; |
309 | auto bounds = filter.value.value<QVariantList>(); | 309 | auto bounds = filter.value.value<QVariantList>(); |
@@ -318,7 +318,7 @@ static QVector<QByteArray> sortedIndexLookup(Index &index, QueryBase::Comparator | |||
318 | 318 | ||
319 | index.rangeLookup(lowerBound, upperBound, | 319 | index.rangeLookup(lowerBound, upperBound, |
320 | [&](const QByteArray &value) { | 320 | [&](const QByteArray &value) { |
321 | keys << Identifier::fromInternalByteArray(value).toDisplayByteArray(); | 321 | keys << Identifier::fromInternalByteArray(value); |
322 | }, | 322 | }, |
323 | [bounds](const Index::Error &error) { | 323 | [bounds](const Index::Error &error) { |
324 | SinkWarning() << "Lookup error in index:" << error.message | 324 | SinkWarning() << "Lookup error in index:" << error.message |
@@ -328,14 +328,14 @@ static QVector<QByteArray> sortedIndexLookup(Index &index, QueryBase::Comparator | |||
328 | return keys; | 328 | return keys; |
329 | } | 329 | } |
330 | 330 | ||
331 | static QVector<QByteArray> sampledIndexLookup(Index &index, QueryBase::Comparator filter) | 331 | static QVector<Identifier> sampledIndexLookup(Index &index, QueryBase::Comparator filter) |
332 | { | 332 | { |
333 | if (filter.comparator != Query::Comparator::Overlap) { | 333 | if (filter.comparator != Query::Comparator::Overlap) { |
334 | SinkWarning() << "Comparisons other than Overlap not supported on sampled period indexes"; | 334 | SinkWarning() << "Comparisons other than Overlap not supported on sampled period indexes"; |
335 | return {}; | 335 | return {}; |
336 | } | 336 | } |
337 | 337 | ||
338 | QVector<QByteArray> keys; | 338 | QVector<Identifier> keys; |
339 | 339 | ||
340 | auto bounds = filter.value.value<QVariantList>(); | 340 | auto bounds = filter.value.value<QVariantList>(); |
341 | 341 | ||
@@ -349,7 +349,7 @@ static QVector<QByteArray> sampledIndexLookup(Index &index, QueryBase::Comparato | |||
349 | 349 | ||
350 | index.rangeLookup(lowerBucket, upperBucket, | 350 | index.rangeLookup(lowerBucket, upperBucket, |
351 | [&](const QByteArray &value) { | 351 | [&](const QByteArray &value) { |
352 | keys << Identifier::fromInternalByteArray(value).toDisplayByteArray(); | 352 | keys << Identifier::fromInternalByteArray(value); |
353 | }, | 353 | }, |
354 | [bounds](const Index::Error &error) { | 354 | [bounds](const Index::Error &error) { |
355 | SinkWarning() << "Lookup error in index:" << error.message | 355 | SinkWarning() << "Lookup error in index:" << error.message |
@@ -359,13 +359,18 @@ static QVector<QByteArray> sampledIndexLookup(Index &index, QueryBase::Comparato | |||
359 | return keys; | 359 | return keys; |
360 | } | 360 | } |
361 | 361 | ||
362 | QVector<QByteArray> TypeIndex::query(const Sink::QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId) | 362 | QVector<Identifier> TypeIndex::query(const Sink::QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId) |
363 | { | 363 | { |
364 | const auto baseFilters = query.getBaseFilters(); | 364 | const auto baseFilters = query.getBaseFilters(); |
365 | for (auto it = baseFilters.constBegin(); it != baseFilters.constEnd(); it++) { | 365 | for (auto it = baseFilters.constBegin(); it != baseFilters.constEnd(); it++) { |
366 | if (it.value().comparator == QueryBase::Comparator::Fulltext) { | 366 | if (it.value().comparator == QueryBase::Comparator::Fulltext) { |
367 | FulltextIndex fulltextIndex{resourceInstanceId}; | 367 | FulltextIndex fulltextIndex{resourceInstanceId}; |
368 | const auto keys = fulltextIndex.lookup(it.value().value.toString()); | 368 | QVector<Identifier> keys; |
369 | const auto ids = fulltextIndex.lookup(it.value().value.toString()); | ||
370 | keys.reserve(ids.size()); | ||
371 | for (const auto &id : ids) { | ||
372 | keys.append(Identifier::fromDisplayByteArray(id)); | ||
373 | } | ||
369 | appliedFilters << it.key(); | 374 | appliedFilters << it.key(); |
370 | SinkTraceCtx(mLogCtx) << "Fulltext index lookup found " << keys.size() << " keys."; | 375 | SinkTraceCtx(mLogCtx) << "Fulltext index lookup found " << keys.size() << " keys."; |
371 | return keys; | 376 | return keys; |
diff --git a/common/typeindex.h b/common/typeindex.h index f2cabaf..875eb7a 100644 --- a/common/typeindex.h +++ b/common/typeindex.h | |||
@@ -94,7 +94,7 @@ public: | |||
94 | void modify(const Sink::Storage::Identifier &identifier, const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, const Sink::ApplicationDomain::ApplicationDomainType &newEntity, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); | 94 | void modify(const Sink::Storage::Identifier &identifier, const Sink::ApplicationDomain::ApplicationDomainType &oldEntity, const Sink::ApplicationDomain::ApplicationDomainType &newEntity, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); |
95 | void remove(const Sink::Storage::Identifier &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); | 95 | void remove(const Sink::Storage::Identifier &identifier, const Sink::ApplicationDomain::ApplicationDomainType &entity, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); |
96 | 96 | ||
97 | QVector<QByteArray> query(const Sink::QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); | 97 | QVector<Sink::Storage::Identifier> query(const Sink::QueryBase &query, QSet<QByteArrayList> &appliedFilters, QByteArray &appliedSorting, Sink::Storage::DataStore::Transaction &transaction, const QByteArray &resourceInstanceId); |
98 | QVector<Sink::Storage::Identifier> lookup(const QByteArray &property, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction); | 98 | QVector<Sink::Storage::Identifier> lookup(const QByteArray &property, const QVariant &value, Sink::Storage::DataStore::Transaction &transaction); |
99 | 99 | ||
100 | template <typename Left, typename Right> | 100 | template <typename Left, typename Right> |