mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-22 12:05:53 +00:00
Add cpu counter
This commit is contained in:
@@ -2,48 +2,79 @@
|
|||||||
#ifndef RIPPLE_BASICS_FUNCTIONPROFILER_H_INCLUDED
|
#ifndef RIPPLE_BASICS_FUNCTIONPROFILER_H_INCLUDED
|
||||||
#define RIPPLE_BASICS_FUNCTIONPROFILER_H_INCLUDED
|
#define RIPPLE_BASICS_FUNCTIONPROFILER_H_INCLUDED
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <unordered_map>
|
|
||||||
#include <sstream>
|
|
||||||
#include <source_location>
|
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <mutex>
|
||||||
|
#include <source_location>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <x86intrin.h>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
void logProfilingResults();
|
void
|
||||||
|
logProfilingResults();
|
||||||
|
|
||||||
class FunctionProfiler
|
class FunctionProfiler
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
std::string functionName;
|
std::string functionName;
|
||||||
std::chrono::steady_clock::time_point start;
|
std::chrono::steady_clock::time_point start;
|
||||||
public:
|
std::uint64_t cpuCycleStart;
|
||||||
|
inline static std::mutex mutex_;
|
||||||
|
|
||||||
inline static std::unordered_map<std::string, std::pair<std::chrono::nanoseconds, std::int64_t>> funcionDurations;
|
struct StatisticData
|
||||||
FunctionProfiler(const std::string& tag, std::source_location location = std::source_location::current()): functionName(location.function_name() + tag), start(std::chrono::steady_clock::now())
|
{
|
||||||
|
std::chrono::nanoseconds timeInTotal;
|
||||||
|
std::uint64_t cpuCyclesInTotal;
|
||||||
|
std::int64_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static std::unordered_map<
|
||||||
|
std::string,
|
||||||
|
StatisticData>
|
||||||
|
funcionDurations;
|
||||||
|
FunctionProfiler(
|
||||||
|
std::string const& tag,
|
||||||
|
std::source_location location = std::source_location::current())
|
||||||
|
: functionName(location.function_name() + tag)
|
||||||
|
, start(std::chrono::steady_clock::now())
|
||||||
|
, cpuCycleStart(__rdtsc())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
~FunctionProfiler() noexcept
|
~FunctionProfiler() noexcept
|
||||||
{
|
{
|
||||||
auto duration = std::chrono::steady_clock::now() - start;
|
auto duration = std::chrono::steady_clock::now() - start;
|
||||||
funcionDurations[functionName].first += std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
|
std::lock_guard<std::mutex> lock{mutex_};
|
||||||
funcionDurations[functionName].second++;
|
if (funcionDurations[functionName].count ==
|
||||||
|
std::numeric_limits<std::int64_t>::max())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
funcionDurations[functionName].timeInTotal += duration;
|
||||||
|
funcionDurations[functionName].cpuCyclesInTotal += (__rdtsc() - cpuCycleStart);
|
||||||
|
funcionDurations[functionName].count++;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::string
|
||||||
inline std::string getProfilingResults()
|
getProfilingResults()
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> lock{FunctionProfiler::mutex_};
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Function profiling results:" << std::endl;
|
ss << "Function profiling results:" << std::endl;
|
||||||
for (const auto& [name, duration] : FunctionProfiler::funcionDurations)
|
ss << "name,time,count" << std::endl;
|
||||||
|
for (auto const& [name, duration] : FunctionProfiler::funcionDurations)
|
||||||
{
|
{
|
||||||
ss << " " << name << ": " << duration.first.count() << " ns" << ", counts: " << duration.second << std::endl;
|
ss << name << "," << duration.first.count() << " ns" << ","
|
||||||
|
<< duration.second << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace beast
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,15 +20,17 @@
|
|||||||
#ifndef BEAST_HASH_XXHASHER_H_INCLUDED
|
#ifndef BEAST_HASH_XXHASHER_H_INCLUDED
|
||||||
#define BEAST_HASH_XXHASHER_H_INCLUDED
|
#define BEAST_HASH_XXHASHER_H_INCLUDED
|
||||||
|
|
||||||
|
#include <xrpl/beast/core/FunctionProfiler.h>
|
||||||
|
|
||||||
#include <boost/endian/conversion.hpp>
|
#include <boost/endian/conversion.hpp>
|
||||||
|
|
||||||
#include <xxhash.h>
|
#include <xxhash.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
#include <iostream>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <type_traits>
|
|
||||||
#include <xrpl/beast/core/FunctionProfiler.h>
|
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
@@ -38,16 +40,29 @@ private:
|
|||||||
// requires 64-bit std::size_t
|
// requires 64-bit std::size_t
|
||||||
static_assert(sizeof(std::size_t) == 8, "");
|
static_assert(sizeof(std::size_t) == 8, "");
|
||||||
|
|
||||||
XXH3_state_t* state_;
|
struct state_wrapper
|
||||||
|
{
|
||||||
|
XXH3_state_t* state;
|
||||||
|
state_wrapper()
|
||||||
|
{
|
||||||
|
state = XXH3_createState();
|
||||||
|
}
|
||||||
|
~state_wrapper()
|
||||||
|
{
|
||||||
|
XXH3_freeState(state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
std::array<std::uint8_t, 40> buffer_;
|
XXH3_state_t* state_;
|
||||||
std::span<std::uint8_t> readSpan_;
|
inline static thread_local state_wrapper wrapper{};
|
||||||
std::span<std::uint8_t> writeSpan_;
|
std::size_t totalSize_ = 0;
|
||||||
XXH64_hash_t seed_{};
|
std::chrono::nanoseconds duration_{};
|
||||||
|
std::uint64_t cpuCycles = 0;
|
||||||
|
|
||||||
static XXH3_state_t*
|
static XXH3_state_t*
|
||||||
allocState()
|
allocState()
|
||||||
{
|
{
|
||||||
|
FunctionProfiler _{"-alloc"};
|
||||||
auto ret = XXH3_createState();
|
auto ret = XXH3_createState();
|
||||||
if (ret == nullptr)
|
if (ret == nullptr)
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
@@ -65,14 +80,24 @@ public:
|
|||||||
|
|
||||||
xxhasher()
|
xxhasher()
|
||||||
{
|
{
|
||||||
state_ = allocState();
|
auto start = std::chrono::steady_clock::now();
|
||||||
XXH3_64bits_reset(state_);
|
auto cpuCyclesStart = __rdtsc();
|
||||||
writeSpan_ = buffer_;
|
// state_ = allocState();
|
||||||
|
// XXH3_64bits_reset(state_);
|
||||||
|
duration_ += std::chrono::steady_clock::now() - start;
|
||||||
|
cpuCycles += (__rdtsc() - cpuCyclesStart);
|
||||||
|
XXH3_64bits_reset(wrapper.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
~xxhasher() noexcept
|
~xxhasher() noexcept
|
||||||
{
|
{
|
||||||
XXH3_freeState(state_);
|
// profiler_.functionName = "xxhasher-" + std::to_string(totalSize_);
|
||||||
|
// auto start = std::chrono::steady_clock::now();
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
FunctionProfiler _{"-free"};
|
||||||
|
XXH3_freeState(state_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@@ -80,10 +105,13 @@ public:
|
|||||||
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||||
explicit xxhasher(Seed seed)
|
explicit xxhasher(Seed seed)
|
||||||
{
|
{
|
||||||
state_ = allocState();
|
auto start = std::chrono::steady_clock::now();
|
||||||
XXH3_64bits_reset_withSeed(state_, seed);
|
auto cpuCyclesStart = __rdtsc();
|
||||||
seed_ = seed;
|
// state_ = allocState();
|
||||||
writeSpan_ = buffer_;
|
// XXH3_64bits_reset_withSeed(state_, seed);
|
||||||
|
XXH3_64bits_reset_withSeed(wrapper.state, seed);
|
||||||
|
duration_ += std::chrono::steady_clock::now() - start;
|
||||||
|
cpuCycles += (__rdtsc() - cpuCyclesStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@@ -91,33 +119,53 @@ public:
|
|||||||
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
std::enable_if_t<std::is_unsigned<Seed>::value>* = nullptr>
|
||||||
xxhasher(Seed seed, Seed)
|
xxhasher(Seed seed, Seed)
|
||||||
{
|
{
|
||||||
state_ = allocState();
|
auto start = std::chrono::steady_clock::now();
|
||||||
XXH3_64bits_reset_withSeed(state_, seed);
|
auto cpuCyclesStart = __rdtsc();
|
||||||
seed_ = seed;
|
// state_ = allocState();
|
||||||
writeSpan_ = buffer_;
|
// XXH3_64bits_reset_withSeed(state_, seed);
|
||||||
|
XXH3_64bits_reset_withSeed(wrapper.state, seed);
|
||||||
|
duration_ += std::chrono::steady_clock::now() - start;
|
||||||
|
cpuCycles += (__rdtsc() - cpuCyclesStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
operator()(void const* key, std::size_t len) noexcept
|
operator()(void const* key, std::size_t len) noexcept
|
||||||
{
|
{
|
||||||
FunctionProfiler _{"-size-" + std::to_string(len)};
|
auto start = std::chrono::steady_clock::now();
|
||||||
//XXH3_64bits_update(state_, key, len);
|
auto cpuCyclesStart = __rdtsc();
|
||||||
if (len >= writeSpan_.size())
|
totalSize_ += len;
|
||||||
{
|
// FunctionProfiler _{"-size-" + std::to_string(len)};
|
||||||
exit(-1);
|
// XXH3_64bits_update(state_, key, len);
|
||||||
}
|
XXH3_64bits_update(wrapper.state, key, len);
|
||||||
std::memcpy(writeSpan_.data(), key, len);
|
duration_ += std::chrono::steady_clock::now() - start;
|
||||||
readSpan_ = std::span<std::uint8_t>(std::begin(buffer_), readSpan_.size() + len);
|
cpuCycles += (__rdtsc() - cpuCyclesStart);
|
||||||
writeSpan_ = std::span<std::uint8_t>(std::begin(buffer_) + readSpan_.size(), buffer_.size() - readSpan_.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit
|
explicit
|
||||||
operator std::size_t() noexcept
|
operator std::size_t() noexcept
|
||||||
{
|
{
|
||||||
FunctionProfiler _{"-digest"};
|
auto start = std::chrono::steady_clock::now();
|
||||||
// XXH3_64bits_update(state_, readSpan_.data(), readSpan_.size());
|
// auto ret = XXH3_64bits_digest(state_);
|
||||||
// return XXH3_64bits_digest(state_);
|
auto ret = XXH3_64bits_digest(wrapper.state);
|
||||||
return XXH64(readSpan_.data(), readSpan_.size(), seed_);
|
duration_ += std::chrono::steady_clock::now() - start;
|
||||||
|
|
||||||
|
if (FunctionProfiler::funcionDurations
|
||||||
|
["xxhasher-" + std::to_string(totalSize_)]
|
||||||
|
.count == std::numeric_limits<std::int64_t>::max())
|
||||||
|
{
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock{FunctionProfiler::mutex_};
|
||||||
|
FunctionProfiler::funcionDurations
|
||||||
|
["xxhasher-" + std::to_string(totalSize_)]
|
||||||
|
.timeInTotal += duration_;
|
||||||
|
FunctionProfiler::funcionDurations
|
||||||
|
["xxhasher-" + std::to_string(totalSize_)]
|
||||||
|
.cpuCyclesInTotal += cpuCycles;
|
||||||
|
FunctionProfiler::funcionDurations
|
||||||
|
["xxhasher-" + std::to_string(totalSize_)]
|
||||||
|
.count++;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user