From 2dc31390dfb98eb98050da3f87dff61bcb42eac3 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@Germany>
Date: Wed, 15 Jun 2016 20:17:44 +0200
Subject: [PATCH] ENH: add some system information when outputting profiling

- basic cpuInfo (model identification, MHz, etc)
- process memInfo

- profiling is activated via the case system/controlDict by
  adding a "profiling" sub-dictionary.

  Simply add the following (everything enabled):

      profiling
      {}

  Which corresponds to the longer form:

      profiling
      {
          active      true;  // default: true
          cpuInfo     true;  // default: true
          memInfo     true;  // default: true
          sysInfo     true;  // default: true
      }

  This can be used to selectively disable any extra information
  (eg, you don't want anyone else to know what hardware was used).
---
 applications/test/sysInfo/Make/files          |   3 +
 applications/test/sysInfo/Make/options        |   0
 applications/test/sysInfo/Test-sysInfo.C      |  46 ++++++
 src/OpenFOAM/Make/files                       |   1 +
 src/OpenFOAM/db/Time/Time.C                   |   9 +-
 src/OpenFOAM/global/profiling/Profiling.C     | 136 ++++++++++++++++--
 src/OpenFOAM/global/profiling/Profiling.H     |  55 +++++--
 .../global/profiling/ProfilingSysInfo.C       |  94 ++++++++++++
 .../global/profiling/ProfilingSysInfo.H       | 115 +++++++++++++++
 9 files changed, 434 insertions(+), 25 deletions(-)
 create mode 100644 applications/test/sysInfo/Make/files
 create mode 100644 applications/test/sysInfo/Make/options
 create mode 100644 applications/test/sysInfo/Test-sysInfo.C
 create mode 100644 src/OpenFOAM/global/profiling/ProfilingSysInfo.C
 create mode 100644 src/OpenFOAM/global/profiling/ProfilingSysInfo.H

diff --git a/applications/test/sysInfo/Make/files b/applications/test/sysInfo/Make/files
new file mode 100644
index 00000000000..74066728871
--- /dev/null
+++ b/applications/test/sysInfo/Make/files
@@ -0,0 +1,3 @@
+Test-sysInfo.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-sysInfo
diff --git a/applications/test/sysInfo/Make/options b/applications/test/sysInfo/Make/options
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/applications/test/sysInfo/Test-sysInfo.C b/applications/test/sysInfo/Test-sysInfo.C
new file mode 100644
index 00000000000..3c04ce0187d
--- /dev/null
+++ b/applications/test/sysInfo/Test-sysInfo.C
@@ -0,0 +1,46 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Application
+
+Description
+
+\*---------------------------------------------------------------------------*/
+
+#include "ProfilingSysInfo.H"
+#include "IOstreams.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+//  Main program:
+
+int main(int argc, char *argv[])
+{
+    Profiling::sysInfo().write(Info);
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index bc9265235fc..ff6fade3be3 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -4,6 +4,7 @@ global/global.Cver
 global/argList/argList.C
 global/clock/clock.C
 global/profiling/Profiling.C
+global/profiling/ProfilingSysInfo.C
 
 bools = primitives/bools
 $(bools)/bool/bool.C
diff --git a/src/OpenFOAM/db/Time/Time.C b/src/OpenFOAM/db/Time/Time.C
index 732dbceb60c..6ec558b5ade 100644
--- a/src/OpenFOAM/db/Time/Time.C
+++ b/src/OpenFOAM/db/Time/Time.C
@@ -337,10 +337,17 @@ void Foam::Time::setControls()
 void Foam::Time::setMonitoring()
 {
     // initialize profiling on request
-    if (controlDict_.lookupOrDefault<Switch>("profiling", false))
+    // skip if 'active' keyword is explicitly set to false
+    const dictionary* profilingDict = controlDict_.subDictPtr("profiling");
+    if
+    (
+        profilingDict
+     && profilingDict->lookupOrDefault<Switch>("active", true)
+    )
     {
         Profiling::initialize
         (
+            *profilingDict,
             IOobject
             (
                 "profiling",
diff --git a/src/OpenFOAM/global/profiling/Profiling.C b/src/OpenFOAM/global/profiling/Profiling.C
index 47db7505b1f..79ffa68aefe 100644
--- a/src/OpenFOAM/global/profiling/Profiling.C
+++ b/src/OpenFOAM/global/profiling/Profiling.C
@@ -24,8 +24,13 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "Profiling.H"
+#include "ProfilingSysInfo.H"
+#include "cpuInfo.H"
+#include "memInfo.H"
+#include "OSspecific.H"
+#include "IOstreams.H"
 #include "dictionary.H"
-
+#include "demandDrivenData.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -36,6 +41,17 @@ Foam::label Foam::Profiling::Information::nextId_(0);
 
 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
 
+// file-scope function
+template<class T>
+inline static void writeEntry
+(
+    Foam::Ostream& os, const Foam::word& key, const T& value
+)
+{
+    os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
+}
+
+
 Foam::label Foam::Profiling::Information::getNextId()
 {
     return nextId_++;
@@ -72,6 +88,34 @@ void Foam::Profiling::initialize
         );
 
         pool_->push(info, pool_->clockTime_);
+        Info<< "Profiling initialized" << nl;
+    }
+}
+
+
+void Foam::Profiling::initialize
+(
+    const dictionary& dict,
+    const IOobject& ioObj,
+    const Time& owner
+)
+{
+    if (pool_)
+    {
+        WarningInFunction
+            << "Already initialized" << endl;
+    }
+    else
+    {
+        pool_ = new Profiling(dict, ioObj, owner);
+
+        Information *info = pool_->store
+        (
+            new Information()
+        );
+
+        pool_->push(info, pool_->clockTime_);
+        Info<< "Profiling initialized" << nl;
     }
 }
 
@@ -146,7 +190,41 @@ Foam::Profiling::Profiling
     clockTime_(),
     hash_(),
     stack_(),
-    timers_()
+    timers_(),
+    sysInfo_(new sysInfo()),
+    cpuInfo_(new cpuInfo()),
+    memInfo_(new memInfo())
+{}
+
+
+Foam::Profiling::Profiling
+(
+    const dictionary& dict,
+    const IOobject& io,
+    const Time& owner
+)
+:
+    regIOobject(io),
+    owner_(owner),
+    clockTime_(),
+    hash_(),
+    stack_(),
+    timers_(),
+    sysInfo_
+    (
+        dict.lookupOrDefault<Switch>("sysInfo", true)
+      ? new sysInfo() : 0
+    ),
+    cpuInfo_
+    (
+        dict.lookupOrDefault<Switch>("cpuInfo", true)
+      ? new cpuInfo() : 0
+    ),
+    memInfo_
+    (
+        dict.lookupOrDefault<Switch>("memInfo", true)
+      ? new memInfo() : 0
+    )
 {}
 
 
@@ -196,6 +274,10 @@ Foam::Profiling::Trigger::Trigger(const string& name)
 
 Foam::Profiling::~Profiling()
 {
+    deleteDemandDrivenData(sysInfo_);
+    deleteDemandDrivenData(cpuInfo_);
+    deleteDemandDrivenData(memInfo_);
+
     if (pool_ == this)
     {
         pool_ = 0;
@@ -281,6 +363,34 @@ bool Foam::Profiling::writeData(Ostream& os) const
     os  << decrIndent
         << indent << token::END_LIST << token::END_STATEMENT << nl;
 
+
+    if (sysInfo_)
+    {
+        os << nl;
+        os.beginBlock("sysInfo") << nl; // FUTURE: without nl
+        sysInfo_->write(os);
+        os.endBlock() << nl; // FUTURE: without nl
+    }
+
+    if (cpuInfo_)
+    {
+        os << nl;
+        os.beginBlock("cpuInfo") << nl; // FUTURE: without nl
+        cpuInfo_->write(os);
+        os.endBlock() << nl; // FUTURE: without nl
+    }
+
+    if (memInfo_)
+    {
+        memInfo_->update();
+
+        os << nl;
+        os.beginBlock("memInfo") << nl; // FUTURE: without nl
+        memInfo_->write(os);
+        writeEntry(os, "units", "kB");
+        os.endBlock() << nl; // FUTURE: without nl
+    }
+
     return os;
 }
 
@@ -312,6 +422,12 @@ Foam::Profiling::Information* Foam::Profiling::pop()
 }
 
 
+bool Foam::Profiling::Trigger::running() const
+{
+    return ptr_;
+}
+
+
 void Foam::Profiling::Trigger::stop()
 {
     if (ptr_)
@@ -324,14 +440,15 @@ void Foam::Profiling::Trigger::stop()
 }
 
 
-// file-scope function
-template<class T>
-inline static void writeEntry
-(
-    Foam::Ostream& os, const Foam::word& key, const T& value
-)
+void Foam::Profiling::Information::push() const
 {
-    os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
+    onStack_ = true;
+}
+
+
+void Foam::Profiling::Information::pop() const
+{
+    onStack_ = false;
 }
 
 
@@ -366,6 +483,7 @@ Foam::Ostream& Foam::Profiling::Information::write
     return os;
 }
 
+
 // * * * * * * * * * * * * * * * Friend Operators  * * * * * * * * * * * * * //
 
 Foam::Ostream& Foam::operator<<
diff --git a/src/OpenFOAM/global/profiling/Profiling.H b/src/OpenFOAM/global/profiling/Profiling.H
index 8e329b7e736..7821dfede55 100644
--- a/src/OpenFOAM/global/profiling/Profiling.H
+++ b/src/OpenFOAM/global/profiling/Profiling.H
@@ -27,6 +27,22 @@ Class
 Description
     Code profiling.
 
+    This is typically activated from within the system/controlDict as follows:
+    \code
+        profiling
+        {
+            active      true;  // default: true
+            cpuInfo     true;  // default: true
+            memInfo     true;  // default: true
+            sysInfo     true;  // default: true
+        }
+    \endcode
+    or simply using all defaults:
+    \code
+        profiling
+        {}
+    \endcode
+
 SourceFiles
     Profiling.C
 
@@ -48,6 +64,9 @@ namespace Foam
 
 // Forward declaration of classes
 class Ostream;
+class dictionary;
+class cpuInfo;
+class memInfo;
 
 /*---------------------------------------------------------------------------*\
                           Class Profiling Declaration
@@ -63,6 +82,7 @@ public:
 
         class Information;
         class Trigger;
+        class sysInfo;
 
 private:
 
@@ -93,6 +113,15 @@ private:
         //- Note the timers (by Id) for the correct stack-output
         Map<clockTime*> timers_;
 
+        //- General system information (optional)
+        sysInfo* sysInfo_;
+
+        //- CPU-Information (optional)
+        cpuInfo* cpuInfo_;
+
+        //- MEM-Information (optional)
+        memInfo* memInfo_;
+
 
     // Private Member Functions
 
@@ -112,9 +141,12 @@ protected:
 
     // Constructors
 
-        //- Construct IO object
+        //- Construct IO object, everything enabled
         Profiling(const IOobject&, const Time&);
 
+        //- Construct IO object with finer control over behaviour
+        Profiling(const dictionary&, const IOobject&, const Time&);
+
 
     //- Destructor
     ~Profiling();
@@ -139,9 +171,12 @@ protected:
 
     // Static control elements
 
-        //- Singleton to initialize profiling pool
+        //- Singleton to initialize profiling pool, everything enabled
         static void initialize(const IOobject&, const Time&);
 
+        //- Singleton to initialize profiling pool with finer control
+        static void initialize(const dictionary&, const IOobject&, const Time&);
+
         //- Stop profiling, cleanup pool if possible
         static void stop(const Time&);
 
@@ -243,17 +278,10 @@ protected:
     // Member Functions
 
         //- Mark as being on the stack
-        void push() const
-        {
-            onStack_ = true;
-        }
-
+        void push() const;
 
         //- Mark as being off the stack
-        void pop() const
-        {
-            onStack_ = false;
-        }
+        void pop() const;
 
 
         //- Write the profiling times, optionally with additional values
@@ -382,10 +410,7 @@ public:
     // Access
 
         //- True if the triggered profiling is active
-        inline bool running() const
-        {
-            return ptr_;
-        }
+        bool running() const;
 
 
     // Edit
diff --git a/src/OpenFOAM/global/profiling/ProfilingSysInfo.C b/src/OpenFOAM/global/profiling/ProfilingSysInfo.C
new file mode 100644
index 00000000000..153fb3c11e2
--- /dev/null
+++ b/src/OpenFOAM/global/profiling/ProfilingSysInfo.C
@@ -0,0 +1,94 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+\*---------------------------------------------------------------------------*/
+
+#include "ProfilingSysInfo.H"
+#include "demandDrivenData.H"
+#include "foamVersion.H"
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+// file-scope function
+template<class T>
+inline static void writeEntry
+(
+    Foam::Ostream& os, const Foam::word& key, const T& value
+)
+{
+    os.writeKeyword(key) << value << Foam::token::END_STATEMENT << '\n';
+}
+
+
+// file-scope function
+inline static void printEnv
+(
+    Foam::Ostream& os, const Foam::word& key, const Foam::word& envName
+)
+{
+    const std::string value = getEnv(envName);
+    if (!value.empty())
+    {
+        writeEntry(os, key, value);
+    }
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
+
+Foam::Profiling::sysInfo::sysInfo()
+{}
+
+
+
+// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
+
+Foam::Profiling::sysInfo::~sysInfo()
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
+
+Foam::Ostream& Foam::Profiling::sysInfo::write
+(
+    Ostream& os
+) const
+{
+    writeEntry(os, "host", hostName(false)); // short name
+    writeEntry(os, "date", clock::dateTime());
+
+    // compile-time information
+    writeEntry(os, "version",     std::string(FOAMversion));
+    writeEntry(os, "build",       std::string(FOAMbuild));
+
+    printEnv(os, "arch",         "WM_ARCH");
+    printEnv(os, "compilerType", "WM_COMPILER_TYPE");
+    printEnv(os, "compiler",     "WM_COMPILER");
+    printEnv(os, "mplib",        "WM_MPLIB");
+    printEnv(os, "options",      "WM_OPTIONS");
+
+    return os;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/global/profiling/ProfilingSysInfo.H b/src/OpenFOAM/global/profiling/ProfilingSysInfo.H
new file mode 100644
index 00000000000..1174082b33b
--- /dev/null
+++ b/src/OpenFOAM/global/profiling/ProfilingSysInfo.H
@@ -0,0 +1,115 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+License
+    This file is part of OpenFOAM.
+
+    OpenFOAM is free software: you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
+    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+    for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
+
+Class
+    Foam::Profiling::SysInfo
+
+Description
+    General system information
+
+SourceFiles
+    ProfilingSysInfo.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef ProfilingSysInfo_H
+#define ProfilingSysInfo_H
+
+#include "Profiling.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration of classes
+class Ostream;
+
+/*---------------------------------------------------------------------------*\
+                     Class Profiling::sysInfo Declaration
+\*---------------------------------------------------------------------------*/
+
+class Profiling::sysInfo
+{
+    // Private Static Data Members
+
+
+    // Private Data Members
+
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        sysInfo(const sysInfo&) = delete;
+
+        //- Disallow default bitwise assignment
+        void operator=(const sysInfo&) = delete;
+
+
+protected:
+
+    // Friendship
+
+        friend class Profiling;
+
+
+    // Member Functions
+
+public:
+
+
+    // Constructors
+
+        //- Construct from components
+        sysInfo();
+
+
+    //- Destructor
+    ~sysInfo();
+
+
+    // Member Functions
+
+    // Access
+
+
+    // Edit
+
+        //- Update it with a new timing information
+        void update();
+
+        //- Write the profiling times, optionally with additional values
+        //  Use dictionary format.
+        Ostream& write(Ostream& os) const;
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
-- 
GitLab