Skip to content

Commit

Permalink
Merge pull request #12940 from KratosMultiphysics/core/profiler
Browse files Browse the repository at this point in the history
Update and Fix `Profiler`
  • Loading branch information
matekelemen authored Dec 16, 2024
2 parents b0bb1cd + f72a6bf commit 06eeea3
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 57 deletions.
91 changes: 46 additions & 45 deletions kratos/sources/profiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,50 @@
#include <algorithm>
#include <thread>
#include <vector>
#include <tuple>
#include <fstream>
#include <sstream>
#include <atomic>
#include <limits> // std::numeric_limits


namespace Kratos::Internals {


namespace {
template <class TTimeUnit>
std::string GetTimeUnit()
{
KRATOS_ERROR << "Unsupported time unit";
}

template <>
std::string GetTimeUnit<std::chrono::milliseconds>()
{
return "ms";
}

template <>
std::string GetTimeUnit<std::chrono::microseconds>()
{
return "us";
}

template <>

std::string GetTimeUnit<std::chrono::nanoseconds>()
{
return "ns";
}
} // unnamed namespace


template <class T>
Profiler<T>::Item::Item(CodeLocation&& rLocation)
: Item(0,
Duration(0),
Duration(0),
Duration(0),
std::move(rLocation))
: Item(0, // <== .mCallCount
Duration(0), // <== .mCumulative
Duration(std::numeric_limits<typename Duration::rep>::max()), // <== .mMin
Duration(0), // <== .mMax
std::move(rLocation)) // <== .mLocation
{
}

Expand Down Expand Up @@ -70,7 +98,7 @@ typename Profiler<T>::Item& Profiler<T>::Item::operator+=(const Item& rOther)

template <class T>
Profiler<T>::Profiler()
: Profiler("kratos_profiler_output.json")
: Profiler("kratos_profiler_output_" + GetTimeUnit<T>() + ".json")
{
}

Expand Down Expand Up @@ -112,34 +140,6 @@ typename Profiler<T>::Item& Profiler<T>::Create(CodeLocation&& r_item)
}


namespace {
template <class TTimeUnit>
std::string GetTimeUnit()
{
KRATOS_ERROR << "Unknown time unit";
}

template <>
std::string GetTimeUnit<std::chrono::milliseconds>()
{
return "ms";
}

template <>
std::string GetTimeUnit<std::chrono::microseconds>()
{
return "us";
}

template <>

std::string GetTimeUnit<std::chrono::nanoseconds>()
{
return "ns";
}
} // unnamed namespace


template <class T>
typename Profiler<T>::ItemMap Profiler<T>::Aggregate() const
{
Expand Down Expand Up @@ -208,7 +208,8 @@ void Profiler<T>::Write(std::ostream& rStream) const
const auto& r_location = p_item->mLocation;
result.AddString("file", std::string(r_location.GetFileName()));
result.AddInt("line", int(r_location.GetLineNumber()));
result.AddString("function", std::string(r_location.GetFunctionName()));
result.AddString("signature", std::string(r_location.GetFunctionName()));
result.AddString("function", std::string(r_location.CleanFunctionName()));
result.AddInt("callCount", p_item->mCallCount);

std::stringstream stream;
Expand Down Expand Up @@ -267,19 +268,19 @@ template <class T>
std::mutex ProfilerSingleton<T>::mMutex;


template class Profiler<std::chrono::milliseconds>;
template class ProfilerSingleton<std::chrono::milliseconds>;
template std::ostream& operator<<(std::ostream&, const Profiler<std::chrono::milliseconds>&);
template class KRATOS_API(KRATOS_CORE) Profiler<std::chrono::milliseconds>;
template class KRATOS_API(KRATOS_CORE) ProfilerSingleton<std::chrono::milliseconds>;
template KRATOS_API(KRATOS_CORE) std::ostream& operator<<(std::ostream&, const Profiler<std::chrono::milliseconds>&);


template class Profiler<std::chrono::microseconds>;
template class ProfilerSingleton<std::chrono::microseconds>;
template std::ostream& operator<<(std::ostream&, const Profiler<std::chrono::microseconds>&);
template class KRATOS_API(KRATOS_CORE) Profiler<std::chrono::microseconds>;
template class KRATOS_API(KRATOS_CORE) ProfilerSingleton<std::chrono::microseconds>;
template KRATOS_API(KRATOS_CORE) std::ostream& operator<<(std::ostream&, const Profiler<std::chrono::microseconds>&);


template class Profiler<std::chrono::nanoseconds>;
template class ProfilerSingleton<std::chrono::nanoseconds>;
template std::ostream& operator<<(std::ostream&, const Profiler<std::chrono::nanoseconds>&);
template class KRATOS_API(KRATOS_CORE) Profiler<std::chrono::nanoseconds>;
template class KRATOS_API(KRATOS_CORE) ProfilerSingleton<std::chrono::nanoseconds>;
template KRATOS_API(KRATOS_CORE) std::ostream& operator<<(std::ostream&, const Profiler<std::chrono::nanoseconds>&);


} // namespace cie::utils
34 changes: 23 additions & 11 deletions kratos/utilities/profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,23 @@ namespace Kratos::Internals {


template <class TTimeUnit>
class Profiler
class KRATOS_API(KRATOS_CORE) Profiler
{
private:
/// @brief Absolute time type.
using TimeUnit = TTimeUnit;

/// @brief Relative time type.
using Duration = TimeUnit;

/// @brief Clock type used for measuring durations.
using Clock = std::chrono::high_resolution_clock;

/// @brief Class for identifying a profiled scope and aggregating its stats.
class Item
{
public:
Item(CodeLocation&& rLocation);
explicit Item(CodeLocation&& rLocation);

private:
Item(std::size_t CallCount,
Expand All @@ -51,40 +54,49 @@ class Profiler
Duration MaxDuration,
CodeLocation&& rLocation);

/// @brief Aggregate profiled data from another @ref Item in the same scope.
Item& operator+=(const Item& rOther);

private:
friend class Profiler;

/// @brief Counter for keeping track of recursive calls.
/// @details Recursive function calls are aggregated onto the top
/// level call. To do that, the @ref Item must keep track
/// of its recursion depth.
unsigned mRecursionLevel;

/// @brief Counter tracking total number of calls to a function during the program's entire execution time.
std::size_t mCallCount;

/// @brief Counter summing the duration of each call to the profiled scope.
Duration mCumulative;

/// @brief Minimum time spent in the profiled scope.
Duration mMin;

/// @brief Maximum time spent in the profiled scope.
Duration mMax;

/// @brief Source information about the profiled scope.
CodeLocation mLocation;
}; // class Item

struct SourceLocationHash
{
std::size_t operator()(const CodeLocation& r_argument) const
std::size_t operator()(const CodeLocation& rArgument) const
{
std::string string(r_argument.GetFileName());
string.append(std::to_string(r_argument.GetLineNumber()));
return std::hash<std::string>()(string);
return std::hash<std::string>()(rArgument.GetFileName() + rArgument.GetFunctionName());
}
};

struct SourceLocationEquality
{
bool operator()(const CodeLocation& r_lhs,
const CodeLocation& r_rhs) const
bool operator()(const CodeLocation& rLhs,
const CodeLocation& rRhs) const
{
return (std::string(r_lhs.GetFileName()) == std::string(r_rhs.GetFileName())) && (r_lhs.GetLineNumber() == r_rhs.GetLineNumber());
return (rLhs.GetFileName() == rRhs.GetFileName())
&& (rLhs.GetFunctionName() == rRhs.GetFunctionName());
}
};

Expand Down Expand Up @@ -180,11 +192,11 @@ class Profiler


template <class T>
std::ostream& operator<<(std::ostream& rStream, const Profiler<T>& rProfiler);
KRATOS_API(KRATOS_CORE) std::ostream& operator<<(std::ostream& rStream, const Profiler<T>& rProfiler);


template <class TTimeUnit>
class ProfilerSingleton
class KRATOS_API(KRATOS_CORE) ProfilerSingleton
{
public:
static Profiler<TTimeUnit>& Get() noexcept;
Expand Down
1 change: 0 additions & 1 deletion kratos/utilities/profiler_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "utilities/profiler.h" // <== help the language server

// System includes
#include <string>
#include <chrono>


Expand Down

0 comments on commit 06eeea3

Please sign in to comment.