Skip to content

Commit 3401404

Browse files
ehellbarktf
authored andcommitted
DPL: use per-path cache entry in ObjectCache
1 parent 83cfd06 commit 3401404

2 files changed

Lines changed: 47 additions & 41 deletions

File tree

Framework/Core/include/Framework/InputRecord.h

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -422,37 +422,35 @@ class InputRecord
422422
auto id = ObjectCache::Id::fromRef(ref);
423423
ConcreteDataMatcher matcher{header->dataOrigin, header->dataDescription, header->subSpecification};
424424
// If the matcher does not have an entry in the cache, deserialise it
425-
// and cache the deserialised object at the given id.
425+
// and cache the deserialised object alongside its id, keyed by path.
426426
auto path = fmt::format("{}", DataSpecUtils::describe(matcher));
427427
LOGP(debug, "{}", path);
428428
auto& cache = mRegistry.get<ObjectCache>();
429429
auto& callbacks = mRegistry.get<CallbackService>();
430-
auto cacheEntry = cache.matcherToId.find(path);
431-
if (cacheEntry == cache.matcherToId.end()) {
432-
cache.matcherToId.insert(std::make_pair(path, id));
430+
auto cacheEntry = cache.matcherToEntry.find(path);
431+
if (cacheEntry == cache.matcherToEntry.end()) {
433432
std::unique_ptr<ValueT const, Deleter<ValueT const>> result(DataRefUtils::as<CCDBSerialized<ValueT>>(ref).release(), false);
434433
void* obj = (void*)result.get();
435434
callbacks.call<CallbackService::Id::CCDBDeserialised>((ConcreteDataMatcher&)matcher, (void*)obj);
436-
cache.idToObject[id] = obj;
435+
cache.matcherToEntry.emplace(path, ObjectCache::Entry{id, obj});
437436
LOGP(info, "Caching in {} ptr to {} ({})", id.value, path, obj);
438437
return result;
439438
}
440-
auto& oldId = cacheEntry->second;
439+
auto& entry = cacheEntry->second;
441440
// The id in the cache is the same, let's simply return it.
442-
if (oldId.value == id.value) {
443-
std::unique_ptr<ValueT const, Deleter<ValueT const>> result((ValueT const*)cache.idToObject[id], false);
441+
if (entry.id.value == id.value) {
442+
std::unique_ptr<ValueT const, Deleter<ValueT const>> result((ValueT const*)entry.obj, false);
444443
LOGP(debug, "Returning cached entry {} for {} ({})", id.value, path, (void*)result.get());
445444
return result;
446445
}
447-
// The id in the cache is different. Let's destroy the old cached entry
448-
// and create a new one.
449-
delete reinterpret_cast<ValueT*>(cache.idToObject[oldId]);
446+
// The id in the cache is different. Destroy this path's previously cached object and replace it.
447+
delete reinterpret_cast<ValueT*>(entry.obj);
450448
std::unique_ptr<ValueT const, Deleter<ValueT const>> result(DataRefUtils::as<CCDBSerialized<ValueT>>(ref).release(), false);
451449
void* obj = (void*)result.get();
452450
callbacks.call<CallbackService::Id::CCDBDeserialised>((ConcreteDataMatcher&)matcher, (void*)obj);
453-
cache.idToObject[id] = obj;
454-
LOGP(info, "Replacing cached entry {} with {} for {} ({})", oldId.value, id.value, path, obj);
455-
oldId.value = id.value;
451+
LOGP(info, "Replacing cached entry {} with {} for {} ({})", entry.id.value, id.value, path, obj);
452+
entry.id = id;
453+
entry.obj = obj;
456454
return result;
457455
} else {
458456
throw runtime_error("Attempt to extract object from message with unsupported serialization type");
@@ -503,30 +501,28 @@ class InputRecord
503501
// it's updated.
504502
auto id = ObjectCache::Id::fromRef(ref);
505503
ConcreteDataMatcher matcher{header->dataOrigin, header->dataDescription, header->subSpecification};
506-
// If the matcher does not have an entry in the cache, deserialise it
507-
// and cache the deserialised object at the given id.
504+
// If the matcher does not have an entry in the cache, deserialise it and cache it per path.
508505
auto path = fmt::format("{}", DataSpecUtils::describe(matcher));
509506
LOGP(debug, "{}", path);
510507
auto& cache = mRegistry.get<ObjectCache>();
511-
auto cacheEntry = cache.matcherToMetadataId.find(path);
512-
if (cacheEntry == cache.matcherToMetadataId.end()) {
513-
cache.matcherToMetadataId.insert(std::make_pair(path, id));
514-
cache.idToMetadata[id] = DataRefUtils::extractCCDBHeaders(ref);
508+
auto cacheEntry = cache.matcherToMetadata.find(path);
509+
if (cacheEntry == cache.matcherToMetadata.end()) {
510+
auto [it, inserted] = cache.matcherToMetadata.emplace(
511+
path, ObjectCache::MetadataEntry{id, DataRefUtils::extractCCDBHeaders(ref)});
515512
LOGP(info, "Caching CCDB metadata {}: {}", id.value, path);
516-
return cache.idToMetadata[id];
513+
return it->second.metadata;
517514
}
518-
auto& oldId = cacheEntry->second;
515+
auto& entry = cacheEntry->second;
519516
// The id in the cache is the same, let's simply return it.
520-
if (oldId.value == id.value) {
517+
if (entry.id.value == id.value) {
521518
LOGP(debug, "Returning cached CCDB metatada {}: {}", id.value, path);
522-
return cache.idToMetadata[id];
519+
return entry.metadata;
523520
}
524-
// The id in the cache is different. Let's destroy the old cached entry
525-
// and create a new one.
526-
LOGP(info, "Replacing cached entry {} with {} for {}", oldId.value, id.value, path);
527-
cache.idToMetadata[id] = DataRefUtils::extractCCDBHeaders(ref);
528-
oldId.value = id.value;
529-
return cache.idToMetadata[id];
521+
// The id in the cache is different. Replace this path's metadata.
522+
LOGP(info, "Replacing cached entry {} with {} for {}", entry.id.value, id.value, path);
523+
entry.id = id;
524+
entry.metadata = DataRefUtils::extractCCDBHeaders(ref);
525+
return entry.metadata;
530526
}
531527

532528
template <typename T = DataRef, typename R>

Framework/Core/include/Framework/ObjectCache.h

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
#include "Framework/DataRef.h"
1515
#include <unordered_map>
1616
#include <map>
17+
#include <string>
1718

1819
namespace o2::framework
1920
{
2021

2122
/// A cache for CCDB objects or objects in general
2223
/// which have more than one timeframe of lifetime.
24+
/// The cache is keyed *per path* rather than by a global id-derived hash.
2325
struct ObjectCache {
2426
struct Id {
2527
int64_t value;
@@ -39,20 +41,28 @@ struct ObjectCache {
3941
}
4042
};
4143
};
42-
/// A cache for deserialised objects.
44+
45+
/// Per-path cache entry for a deserialised CCDB object.
46+
struct Entry {
47+
Id id{0};
48+
void* obj{nullptr};
49+
};
50+
51+
/// Per-path cache entry for the CCDB metadata map.
52+
struct MetadataEntry {
53+
Id id{0};
54+
std::map<std::string, std::string> metadata;
55+
};
56+
57+
/// A per-path cache for deserialised objects.
4358
/// This keeps a mapping so that we can tell if a given
44-
/// path was already received and it's blob stored in
45-
/// .second.
46-
std::unordered_map<std::string, Id> matcherToId;
47-
/// A map from a CacheId (which is the void* ptr of the previous map).
48-
/// to an actual (type erased) pointer to the deserialised object.
49-
std::unordered_map<Id, void*, Id::hash_fn> idToObject;
50-
51-
/// A cache to the deserialised metadata
59+
/// path was already received and it's blob stored in .second.obj
60+
std::unordered_map<std::string, Entry> matcherToEntry;
61+
62+
/// A per-path cache to the deserialised metadata
5263
/// We keep it separate because we want to avoid that looking up
5364
/// the metadata also pollutes the object cache.
54-
std::unordered_map<std::string, Id> matcherToMetadataId;
55-
std::unordered_map<Id, std::map<std::string, std::string>, Id::hash_fn> idToMetadata;
65+
std::unordered_map<std::string, MetadataEntry> matcherToMetadata;
5666
};
5767

5868
} // namespace o2::framework

0 commit comments

Comments
 (0)