Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

See https://github.com/AIDASoft/DD4hep/pull/1288 Add example for illustration #1289

Merged
merged 2 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307 changes: 307 additions & 0 deletions DDG4/plugins/Geant4DetectorConstructionResources.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
//==========================================================================
// AIDA Detector description implementation
//--------------------------------------------------------------------------
// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
// All rights reserved.
//
// For the licensing terms see $DD4hepINSTALL/LICENSE.
// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
//
// \author Markus Frank
// \date 2015-11-09
//
//==========================================================================

// Framework include files
#include <DDG4/Geant4DetectorConstruction.h>

// C/C++ include files

/// Namespace for the AIDA detector description toolkit
namespace dd4hep {

/// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit
namespace sim {

/// Debug class to dump resources usage during detector construction
/**
* Debug class to dump resources usage during detector construction
*
* \author M.Frank
* \version 1.0
* \ingroup DD4HEP_SIMULATION
*/
class Geant4DetectorConstructionResources : public Geant4DetectorConstruction {
public:
/// Class to store the status information of a process from /proc/<pid>/status
/**
*
* \author M.Frank
* \version 1.0
*/
class __attribute__((__packed__)) StatusProcess {
public:
char comm[399];
char state;
int umask;
int tgid;
int ngid;
int pid;
int ppid;
int uid;
int gid;
int utrace;
int fdSize;
long vmPeak;
long vmSize;
long vmLock;
long vmPin;
long vmHWM;
long vmRSS;
long vmRSSano;
long vmRSSfil;
long vmRSSshm;
long vmData;
long vmStack;
long vmExe;
long vmLib;
long vmPTE;
long vmSwap;
/// Default constructor
StatusProcess() {}
};
std::unique_ptr<StatusProcess> snapshot;
std::string when { "geometry|sensitives" };

void print_status(const char* tag, const StatusProcess& sp) const;

public:
/// Initializing constructor for DDG4
Geant4DetectorConstructionResources(Geant4Context* ctxt, const std::string& nam);
/// Default destructor
virtual ~Geant4DetectorConstructionResources();
/// Sensitive detector construction callback. Called at "Construct()"
virtual void constructGeo(Geant4DetectorConstructionContext*) override;
/// Sensitives construction callback. Called at "ConstructSDandField()"
virtual void constructSensitives(Geant4DetectorConstructionContext* ctxt) override;
};
} // End namespace sim
} // End namespace dd4hep


// Framework include files
#include <DD4hep/InstanceCount.h>
#include <DD4hep/Printout.h>
#include <DD4hep/Plugins.h>
#include <DD4hep/Detector.h>

#include <DDG4/Geant4Mapping.h>
#include <DDG4/Geant4Kernel.h>
#include <DDG4/Factories.h>

#include <stdexcept>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

using namespace dd4hep::sim;

DECLARE_GEANT4ACTION(Geant4DetectorConstructionResources)

namespace {

class SysFile {
public:
class FileDescriptor {
/// File handle
int m_fd;

public:
/// Initializing constructor
FileDescriptor(int value) : m_fd(value) {}
/// Default destructor. Non-virtuality is intended. Do not inherit!
~FileDescriptor();
/// Access file handle
int get() const { return m_fd; }
};


public:
/// File name
std::string m_name;
/// Initializing constructor
SysFile(const char* name) : m_name(name) {}
/// Initializing constructor
SysFile(const std::string& name) : m_name(name) {}
/// Default destructor. Non-virtuality is intended. Do not inherit!
~SysFile() {}
/// Read buffer from file in one go
int read(char* buffer, size_t len) const;
};

/// Default destructor. Non-virtuality is intended. Do not inherit!
SysFile::FileDescriptor::~FileDescriptor() {
if (m_fd > 0) ::close(m_fd);
m_fd = 0;
}

/// Read buffer from file in one go
int SysFile::read(char* buf, size_t siz) const {
FileDescriptor fd(::open(m_name.c_str(),O_RDONLY));
if( fd.get() < 0 ) {
std::string err = "Failed to open "+m_name+" ";
throw std::runtime_error(err+std::make_error_code(std::errc(errno)).message());
}
std::size_t tmp = 0;
while ( tmp < siz ) {
int sc = ::read(fd.get(),buf+tmp,siz-tmp);
if ( sc > 0 ) {
tmp += sc;
}
else if ( sc == 0 ) {
buf[tmp] = 0;
return tmp;
}
else if ( errno == EINTR ) {
printf("EINTR~!!!!\n");
continue;
}
else {
break;
}
}
if ( tmp != siz ) {
std::string err = "Read of system file "+m_name+" failed:";
throw std::runtime_error(err+std::make_error_code(std::errc(errno)).message());
}
return tmp;
}

int read_info(Geant4DetectorConstructionResources::StatusProcess& proc, int proc_id) {
char buff[2048], *ptr=buff;
std::string fn = "/proc/"+std::to_string(proc_id)+"/status";
int nitem=0, cnt=SysFile(fn.c_str()).read(buff,sizeof(buff));
if(cnt>0) {
int ival;
long int lval;

while(ptr && ptr<(buff+cnt)) {
char* p = ::strchr(ptr,'\t');
char* end = ::strchr(ptr,'\n');

ptr = (end) ? end+1 : 0;
if ( 0 == p ) continue;
++p;
switch(++nitem) {
case 1: ::sscanf(p,"%s",proc.comm); break;
case 2: ::sscanf(p,"%d",&ival); proc.umask = ival; break;
case 3: ::sscanf(p,"%c",&proc.state); break;
case 4: ::sscanf(p,"%d",&ival); proc.tgid = ival; break;
case 5: ::sscanf(p,"%d",&ival); proc.ngid = ival; break;
case 6: ::sscanf(p,"%d",&ival); proc.pid = ival; break;
case 7: ::sscanf(p,"%d",&ival); proc.ppid = ival; break;
case 8: ::sscanf(p,"%d",&ival); proc.utrace = ival; break;
case 9: ::sscanf(p,"%d",&ival); proc.uid = ival; break;
case 10: ::sscanf(p,"%d",&ival); proc.gid = ival; break;
case 11: ::sscanf(p,"%d",&ival); proc.fdSize = ival; break;
case 17: ::sscanf(p,"%ld",&lval); proc.vmPeak = lval; break;
case 18: ::sscanf(p,"%ld",&lval); proc.vmSize = lval; break;
case 19: ::sscanf(p,"%ld",&lval); proc.vmLock = lval; break;
case 20: ::sscanf(p,"%ld",&lval); proc.vmPin = lval; break;
case 21: ::sscanf(p,"%ld",&lval); proc.vmHWM = lval; break;
case 22: ::sscanf(p,"%ld",&lval); proc.vmRSS = lval; break;
case 23: ::sscanf(p,"%ld",&lval); proc.vmRSSano= lval; break;
case 24: ::sscanf(p,"%ld",&lval); proc.vmRSSfil= lval; break;
case 25: ::sscanf(p,"%ld",&lval); proc.vmRSSshm= lval; break;
case 26: ::sscanf(p,"%ld",&lval); proc.vmData = lval; break;
case 27: ::sscanf(p,"%ld",&lval); proc.vmStack = lval; break;
case 28: ::sscanf(p,"%ld",&lval); proc.vmExe = lval; break;
case 29: ::sscanf(p,"%ld",&lval); proc.vmLib = lval; break;
case 30: ::sscanf(p,"%ld",&lval); proc.vmPTE = lval; break;
case 31: ::sscanf(p,"%ld",&lval); proc.vmSwap = lval; break;
case 32: return 1;
default: break;
}
}
return 1;
}
return 0;
}
}

/// Initializing constructor for other clients
Geant4DetectorConstructionResources::Geant4DetectorConstructionResources(Geant4Context* ctxt, const std::string& nam)
: Geant4DetectorConstruction(ctxt,nam)
{
declareProperty("When", this->when);
InstanceCount::increment(this);
}

/// Default destructor
Geant4DetectorConstructionResources::~Geant4DetectorConstructionResources() {
InstanceCount::decrement(this);
}

/// Sensitive detector construction callback. Called at "Construct()"
void Geant4DetectorConstructionResources::constructGeo(Geant4DetectorConstructionContext*) {
if ( this->when.find("geometry") != std::string::npos ) {
this->snapshot = std::make_unique<StatusProcess>();
read_info(*this->snapshot, ::getpid());
this->print_status("ConstructGeo: ", *this->snapshot);
}
}

void Geant4DetectorConstructionResources::print_status(const char* tag, const StatusProcess& sp) const {
this->always("%s Name: \t%s", tag, sp.comm);
this->always("%s State: \t%c", tag, sp.state);
this->always("%s Umask: \t%8d", tag, sp.umask);
this->always("%s Tgid: \t%8d", tag, sp.tgid);
this->always("%s Pid: \t%8d", tag, sp.pid);
this->always("%s PPid: \t%8d", tag, sp.ppid);
this->always("%s utrace: \t%8d", tag, sp.utrace);
this->always("%s Uid: \t%8d", tag, sp.uid);
this->always("%s Gid: \t%8d", tag, sp.gid);
this->always("%s FDSize: \t%8d", tag, sp.fdSize);
this->always("%s VmPeak: \t%8ld kB", tag, sp.vmPeak);
this->always("%s VmSize: \t%8ld kB", tag, sp.vmSize);
this->always("%s VmLck: \t%8ld kB", tag, sp.vmLock);
this->always("%s VmHWM: \t%8ld kB", tag, sp.vmHWM);
this->always("%s VmRSS: \t%8ld kB", tag, sp.vmRSS);
this->always("%s VmRSS anon: \t%8ld kB", tag, sp.vmRSSano);
this->always("%s VmRSS file: \t%8ld kB", tag, sp.vmRSSfil);
this->always("%s VmRSS shm: \t%8ld kB", tag, sp.vmRSSshm);
this->always("%s VmData: \t%8ld kB", tag, sp.vmData);
this->always("%s VmStk: \t%8ld kB", tag, sp.vmStack);
this->always("%s VmExe: \t%8ld kB", tag, sp.vmExe);
this->always("%s VmLib: \t%8ld kB", tag, sp.vmLib);
this->always("%s VmPTE: \t%8ld kB", tag, sp.vmPTE);
}

/// Sensitive detector construction callback. Called at "ConstructSDandField()"
void Geant4DetectorConstructionResources::constructSensitives(Geant4DetectorConstructionContext*) {
if ( this->when.find("sensitives") != std::string::npos ) {
StatusProcess rd;
read_info(rd, ::getpid());
this->print_status("ConstructSD: ", rd);
#if 0
if ( snapshot ) {
const auto& snap = *this->snapshot;
this->always(" --> DIFFERENCE: FDSize: \t%8d", rd.fdSize - snap.fdSize);
this->always(" --> DIFFERENCE: VmPeak: \t%8ld kB", rd.vmPeak - snap.vmPeak);
this->always(" --> DIFFERENCE: VmSize: \t%8ld kB", rd.vmSize - snap.vmSize);
this->always(" --> DIFFERENCE: VmLck: \t%8ld kB", rd.vmLock - snap.vmLock);
this->always(" --> DIFFERENCE: VmHWM: \t%8ld kB", rd.vmHWM - snap.vmHWM);
this->always(" --> DIFFERENCE: VmRSS: \t%8ld kB", rd.vmRSS - snap.vmRSS);
this->always(" --> DIFFERENCE: VmRSS anon: \t%8ld kB", rd.vmRSSano - snap.vmRSSano);
this->always(" --> DIFFERENCE: VmRSS file: \t%8ld kB", rd.vmRSSfil - snap.vmRSSfil);
this->always(" --> DIFFERENCE: VmRSS shm: \t%8ld kB", rd.vmRSSshm - snap.vmRSSshm);
this->always(" --> DIFFERENCE: VmData: \t%8ld kB", rd.vmData - snap.vmData);
this->always(" --> DIFFERENCE: VmStk: \t%8ld kB", rd.vmStack - snap.vmStack);
this->always(" --> DIFFERENCE: VmExe: \t%8ld kB", rd.vmExe - snap.vmExe);
this->always(" --> DIFFERENCE: VmLib: \t%8ld kB", rd.vmLib - snap.vmLib);
this->always(" --> DIFFERENCE: VmPTE: \t%8ld kB", rd.vmPTE - snap.vmPTE);
}
#endif
}
snapshot.reset();
}
18 changes: 18 additions & 0 deletions examples/ClientTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -614,4 +614,22 @@ if (DD4HEP_USE_GEANT4)
REGEX_FAIL "Error;ERROR; Exception"
)
endif()
#
# Test Geant4VolumeManager resource usage
dd4hep_add_test_reg(ClientTests_g4_setup_BoxOfStraws_sensitive
COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh"
EXEC_ARGS ${Python_EXECUTABLE} ${ClientTestsEx_INSTALL}/scripts/BoxOfStraws.py
-print_level 3 -sensitive
REGEX_PASS "ResourcesAfterConstruction ConstructSD: VmRSS"
REGEX_FAIL "Error;ERROR; Exception"
)
#
# Test without Geant4VolumeManager, but sensitive detector assignment using regex
dd4hep_add_test_reg(ClientTests_g4_setup_BoxOfStraws_non_sensitive
COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh"
EXEC_ARGS ${Python_EXECUTABLE} ${ClientTestsEx_INSTALL}/scripts/BoxOfStraws.py
-print_level 3
REGEX_PASS "ResourcesAfterConstruction ConstructSD: VmRSS"
REGEX_FAIL "Error;ERROR; Exception"
)
endif(DD4HEP_USE_GEANT4)
Loading
Loading