Skip to content
Snippets Groups Projects
Commit 6587b658 authored by Philippe Canal's avatar Philippe Canal
Browse files

TIsAProxy retain last 8 matches (rather than 1).

This allows to significant reduce the number of search through the list of cached result ...
That search was a noticeable cause of slow down with an increase of number threads due to the contention
on updating the number of readers (used for the local read/write lock mechanism).
parent d519905b
No related branches found
No related tags found
No related merge requests found
...@@ -28,14 +28,22 @@ class TIsAProxy : public TVirtualIsAProxy { ...@@ -28,14 +28,22 @@ class TIsAProxy : public TVirtualIsAProxy {
private: private:
template <typename T> using Atomic_t = std::atomic<T>; template <typename T> using Atomic_t = std::atomic<T>;
// On testing with the data from the 250202_181_RECO.root and doing "just" serializing
// the value 8 was the sweet spot of performance. With more slots, too much time is
// spent scanning the array of "last" seen and with less slots then the
// serialization induced by and/or the cost of executed `++fSubTypesReaders is slow
// down (noticeably) the streaming of branches with polymorphic containers.
static constexpr UInt_t fgMaxLastSlot = 8;
const std::type_info *fType; //Actual typeid of the proxy const std::type_info *fType; //Actual typeid of the proxy
Atomic_t<TClass*> fClass; //Actual TClass Atomic_t<TClass*> fClass; //Actual TClass
Atomic_t<void*> fLast; //points into fSubTypes map for last used values
Char_t fSubTypes[72];//map of known sub-types Char_t fSubTypes[72];//map of known sub-types
mutable Atomic_t<UInt_t> fSubTypesReaders; //number of readers of fSubTypes mutable Atomic_t<UInt_t> fSubTypesReaders; //number of readers of fSubTypes
Atomic_t<Bool_t> fSubTypesWriteLockTaken; //True if there is a writer Atomic_t<Bool_t> fSubTypesWriteLockTaken; //True if there is a writer
Bool_t fVirtual; //Flag if class is virtual Bool_t fVirtual; //Flag if class is virtual
Atomic_t<Bool_t> fInit; //Initialization flag Atomic_t<Bool_t> fInit; //Initialization flag
Atomic_t<void*> fLasts[fgMaxLastSlot]; // points into fSubTypes map for last used values
Atomic_t<UChar_t> fNextLastSlot;// Next slot in fLasts to use for update (ring buffer)
void* FindSubType(const std::type_info*) const; void* FindSubType(const std::type_info*) const;
void* CacheSubType(const std::type_info*, TClass*); void* CacheSubType(const std::type_info*, TClass*);
......
...@@ -39,19 +39,22 @@ namespace { ...@@ -39,19 +39,22 @@ namespace {
{ {
return (ClassMap_t::value_type*)p; return (ClassMap_t::value_type*)p;
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// Standard initializing constructor /// Standard initializing constructor
TIsAProxy::TIsAProxy(const std::type_info& typ) TIsAProxy::TIsAProxy(const std::type_info& typ)
: fType(&typ), fClass(nullptr), fLast(nullptr), : fType(&typ), fClass(nullptr),
fSubTypesReaders(0), fSubTypesWriteLockTaken(kFALSE), fSubTypesReaders(0), fSubTypesWriteLockTaken(kFALSE),
fVirtual(kFALSE), fInit(kFALSE) fVirtual(kFALSE), fInit(kFALSE)
{ {
static_assert(sizeof(ClassMap_t)<=sizeof(fSubTypes), "ClassMap size is to large for array"); static_assert(sizeof(ClassMap_t)<=sizeof(fSubTypes), "ClassMap size is to large for array");
::new(fSubTypes) ClassMap_t(); ::new(fSubTypes) ClassMap_t();
for(auto& slot : fLasts)
slot = nullptr;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -72,7 +75,8 @@ void TIsAProxy::SetClass(TClass *cl) ...@@ -72,7 +75,8 @@ void TIsAProxy::SetClass(TClass *cl)
{ {
GetMap(fSubTypes)->clear(); GetMap(fSubTypes)->clear();
fClass = cl; fClass = cl;
fLast = nullptr; for(auto& slot : fLasts)
slot = nullptr;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -106,20 +110,30 @@ TClass* TIsAProxy::operator()(const void *obj) ...@@ -106,20 +110,30 @@ TClass* TIsAProxy::operator()(const void *obj)
if ( typ == fType ) { if ( typ == fType ) {
return fClass.load(); return fClass.load();
} }
auto last = ToPair(fLast.load()); for(auto& slot : fLasts) {
if ( last && typ == last->first ) { auto last = ToPair(slot);
return last->second; if ( last && typ == last->first ) {
return last->second;
}
} }
// Check if type is already in sub-class cache // Check if type is already in sub-class cache
last = ToPair(FindSubType(typ)); auto last = ToPair(FindSubType(typ));
if ( last == nullptr || last->second == nullptr ) { if ( last == nullptr || last->second == nullptr ) {
// Last resort: lookup root class // Last resort: lookup root class
auto cls = TClass::GetClass(*typ); auto cls = TClass::GetClass(*typ);
last = ToPair(CacheSubType(typ,cls)); last = ToPair(CacheSubType(typ,cls));
} }
fLast.store(last);
return last == nullptr? nullptr: last->second; UChar_t next = fNextLastSlot++;
if (next >= fgMaxLastSlot) {
UChar_t expected_value = next + 1;
next = next % fgMaxLastSlot;
fNextLastSlot.compare_exchange_strong(expected_value, next + 1);
}
fLasts[next].store(last);
return last == nullptr ? nullptr: last->second;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment