Skip to content
Snippets Groups Projects
Commit 05e4a2ac authored by Frank Winklmeier's avatar Frank Winklmeier
Browse files

DataObjID: on-demand lookup of className

Retrieving the class name to a CLID requires querying the `ClassIDSvc`,
which (at least in the ATLAS implementation) requires taking a lock
during the lookup and in general might be a costly operation. Instead of
doing this in the construction of `DataObjID` only lookup the
class name when needed and then cache the result.

Also cleanup the needlessly complicated code of one-time retrieval of
ClassIDSvc by using a simple static.

This fixes some performance problems in multi-threaded ATLAS
jobs (ATEAM-1054).
parent 979e3109
No related branches found
No related tags found
No related merge requests found
Pipeline #10564816 failed
/***********************************************************************************\
* (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
* *
* This software is distributed under the terms of the Apache version 2 licence, *
* copied verbatim in the file "LICENSE". *
......@@ -15,6 +15,7 @@
#include <GaudiKernel/StatusCode.h>
#include <iostream>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_set>
......@@ -48,19 +49,27 @@ class DataObjID {
public:
friend DataObjID_Hasher;
DataObjID() = default;
DataObjID( const DataObjID& ) = default;
DataObjID() = default;
DataObjID( const DataObjID& other )
: m_clid( other.m_clid ), m_hash( other.m_hash ), m_key( other.m_key ), m_className( other.m_className ) {}
DataObjID( std::string key );
DataObjID( const CLID& clid, std::string key );
DataObjID( std::string className, std::string key );
DataObjID& operator=( const DataObjID& ) = default;
DataObjID& operator=( const DataObjID& other ) {
m_clid = other.m_clid;
m_hash = other.m_hash;
m_key = other.m_key;
m_className = other.m_className;
return *this;
}
/// only return the last part of the key
const std::string& key() const { return m_key; }
/// return the ClassName (if available)
const std::string& className() const { return m_className; }
const std::string& className() const;
/// combination of the key and the ClassName, mostly for debugging
std::string fullKey() const;
......@@ -81,22 +90,18 @@ public:
private:
void hashGen();
void setClid();
void setClassName();
CLID m_clid{ 0 };
std::size_t m_hash{ 0 };
std::string m_key{ "INVALID" };
std::string m_className;
static IClassIDSvc* p_clidSvc;
static std::once_flag m_ip;
std::string m_key{ "INVALID" };
mutable std::string m_className;
mutable std::once_flag m_setClassName;
};
inline DataObjID::DataObjID( std::string key ) : m_key( std::move( key ) ) { hashGen(); }
inline DataObjID::DataObjID( const CLID& clid, std::string key ) : m_clid( clid ), m_key( std::move( key ) ) {
setClassName();
hashGen();
}
......@@ -136,7 +141,7 @@ namespace Gaudi {
DataObjIDVector fromString( const DataObjIDVector&, const std::string& );
};
} // namespace Property
} // namespace Details
} // namespace Details
} // namespace Gaudi
#endif
/***********************************************************************************\
* (c) Copyright 1998-2024 CERN for the benefit of the LHCb and ATLAS collaborations *
* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
* *
* This software is distributed under the terms of the Apache version 2 licence, *
* copied verbatim in the file "LICENSE". *
......@@ -56,31 +56,22 @@ namespace Gaudi {
StatusCode parse( DataObjID& dest, std::string_view src ) { return Gaudi::Parsers::parse_( dest, quote( src ) ); }
IClassIDSvc* DataObjID::p_clidSvc( nullptr );
std::once_flag DataObjID::m_ip;
namespace {
auto getClidSvc = []( std::reference_wrapper<IClassIDSvc*> p ) {
p.get() = Gaudi::svcLocator()->service<IClassIDSvc>( "ClassIDSvc" ).get();
/// Helper to retrieve and cache pointer to ClassIDSvc if available
IClassIDSvc* getClidSvc() {
static IClassIDSvc* clidSvc = Gaudi::svcLocator()->service<IClassIDSvc>( "ClassIDSvc" ).get();
return clidSvc;
};
}
} // namespace
void DataObjID::setClid() {
std::call_once( m_ip, getClidSvc, std::ref( p_clidSvc ) );
if ( !p_clidSvc || p_clidSvc->getIDOfTypeName( m_className, m_clid ).isFailure() ) {
if ( !getClidSvc() || getClidSvc()->getIDOfTypeName( m_className, m_clid ).isFailure() ) {
m_clid = 0;
m_className = "UNKNOWN_CLASS:" + m_className;
}
}
void DataObjID::setClassName() {
std::call_once( m_ip, getClidSvc, std::ref( p_clidSvc ) );
if ( !p_clidSvc || p_clidSvc->getTypeNameOfID( m_clid, m_className ).isFailure() ) {
m_className = "UNKNOW_CLID:" + std::to_string( m_clid );
}
}
void DataObjID::hashGen() {
m_hash = ( std::hash<std::string>()( m_key ) );
if ( m_clid != 0 ) {
......@@ -92,12 +83,25 @@ void DataObjID::hashGen() {
#include <GaudiKernel/ToStream.h>
std::ostream& toStream( const DataObjID& d, std::ostream& os ) {
using Gaudi::Utils::toStream;
return ( d.m_clid != 0 || !d.m_className.empty() ) ? toStream( std::tie( d.m_className, d.m_key ), os )
return ( d.m_clid != 0 || !d.className().empty() ) ? toStream( std::tie( d.className(), d.m_key ), os )
: toStream( d.m_key, os );
}
const std::string& DataObjID::className() const {
// Set class name once if not done already
if ( m_className.empty() ) {
std::call_once( m_setClassName, [&]() {
if ( !getClidSvc() || getClidSvc()->getTypeNameOfID( m_clid, m_className ).isFailure() ) {
m_className = "UNKNOWN_CLID:" + std::to_string( m_clid );
}
} );
}
return m_className;
}
std::string DataObjID::fullKey() const {
return ( m_clid == 0 && m_className.empty() ) ? m_key : ( m_className + '/' + m_key );
return ( m_clid == 0 && className().empty() ) ? m_key : ( className() + '/' + m_key );
}
std::string Gaudi::Details::Property::StringConverter<DataObjIDColl>::toString( const DataObjIDColl& v ) {
......
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