mirror of
https://github.com/ton-blockchain/ton
synced 2025-03-09 15:40:10 +00:00
celldb in-memory mode, stats for actors, perf counters, minor fix in rldp2 (#1164)
* getactorstats query for validator-engine-console * celldb in-memory mode (--celldb-in-memory option) * rldp2: bugfix - do not estimate speed while nothing is sent * add simple ed25519 benchmark * fix compilation errors of different platforms and move to c++20 * fix some warnings * turn on TON_USE_ABSEIL for glibc 2.27 nix build --------- Co-authored-by: birydrad <>
This commit is contained in:
parent
5f51d3d04f
commit
72020c04c4
100 changed files with 3407 additions and 359 deletions
|
@ -22,6 +22,7 @@
|
|||
|
||||
#if TD_HAVE_ABSL
|
||||
#include <absl/container/flat_hash_map.h>
|
||||
#include <absl/container/node_hash_map.h>
|
||||
#else
|
||||
#include <unordered_map>
|
||||
#endif
|
||||
|
@ -31,9 +32,13 @@ namespace td {
|
|||
#if TD_HAVE_ABSL
|
||||
template <class Key, class Value, class H = Hash<Key>>
|
||||
using HashMap = absl::flat_hash_map<Key, Value, H>;
|
||||
template <class Key, class Value, class H = Hash<Key>, class E = std::equal_to<>>
|
||||
using NodeHashMap = absl::node_hash_map<Key, Value, H, E>;
|
||||
#else
|
||||
template <class Key, class Value, class H = Hash<Key>>
|
||||
using HashMap = std::unordered_map<Key, Value, H>;
|
||||
template <class Key, class Value, class H = Hash<Key>>
|
||||
using NodeHashMap = std::unordered_map<Key, Value, H>;
|
||||
#endif
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
#if TD_HAVE_ABSL
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <absl/container/node_hash_set.h>
|
||||
#else
|
||||
#include <unordered_set>
|
||||
#endif
|
||||
|
@ -29,11 +30,15 @@
|
|||
namespace td {
|
||||
|
||||
#if TD_HAVE_ABSL
|
||||
template <class Key, class H = Hash<Key>>
|
||||
using HashSet = absl::flat_hash_set<Key, H>;
|
||||
template <class Key, class H = Hash<Key>, class E = std::equal_to<>>
|
||||
using HashSet = absl::flat_hash_set<Key, H, E>;
|
||||
template <class Key, class H = Hash<Key>, class E = std::equal_to<>>
|
||||
using NodeHashSet = absl::node_hash_set<Key, H, E>;
|
||||
#else
|
||||
template <class Key, class H = Hash<Key>>
|
||||
using HashSet = std::unordered_set<Key, H>;
|
||||
template <class Key, class H = Hash<Key>, class E = std::equal_to<>>
|
||||
using HashSet = std::unordered_set<Key, H, E>;
|
||||
template <class Key, class H = Hash<Key>, class E = std::equal_to<>>
|
||||
using NodeHashSet = HashSet<Key, H, E>;
|
||||
#endif
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -32,12 +32,7 @@ class HazardPointers {
|
|||
explicit HazardPointers(size_t threads_n) : threads_(threads_n) {
|
||||
for (auto &data : threads_) {
|
||||
for (auto &ptr : data.hazard_) {
|
||||
// workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64658
|
||||
#if TD_GCC && GCC_VERSION <= 40902
|
||||
ptr = nullptr;
|
||||
#else
|
||||
std::atomic_init(&ptr, static_cast<T *>(nullptr));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,6 +115,22 @@ class StealingQueue {
|
|||
std::atomic_thread_fence(std::memory_order_seq_cst);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
while (true) {
|
||||
auto head = head_.load();
|
||||
auto tail = tail_.load(std::memory_order_acquire);
|
||||
|
||||
if (tail < head) {
|
||||
continue;
|
||||
}
|
||||
size_t n = tail - head;
|
||||
if (n > N) {
|
||||
continue;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::atomic<td::int64> head_{0};
|
||||
std::atomic<td::int64> tail_{0};
|
||||
|
|
|
@ -137,4 +137,55 @@ class NamedThreadSafeCounter {
|
|||
Counter counter_;
|
||||
};
|
||||
|
||||
// another class for simplicity, it
|
||||
struct NamedPerfCounter {
|
||||
public:
|
||||
static NamedPerfCounter &get_default() {
|
||||
static NamedPerfCounter res;
|
||||
return res;
|
||||
}
|
||||
struct PerfCounterRef {
|
||||
NamedThreadSafeCounter::CounterRef count;
|
||||
NamedThreadSafeCounter::CounterRef duration;
|
||||
};
|
||||
PerfCounterRef get_counter(Slice name) {
|
||||
return {.count = counter_.get_counter(PSLICE() << name << ".count"),
|
||||
.duration = counter_.get_counter(PSLICE() << name << ".duration")};
|
||||
}
|
||||
|
||||
struct ScopedPerfCounterRef : public NoCopyOrMove {
|
||||
PerfCounterRef perf_counter;
|
||||
uint64 started_at_ticks{td::Clocks::rdtsc()};
|
||||
|
||||
~ScopedPerfCounterRef() {
|
||||
perf_counter.count.add(1);
|
||||
perf_counter.duration.add(td::Clocks::rdtsc() - started_at_ticks);
|
||||
}
|
||||
};
|
||||
|
||||
template <class F>
|
||||
void for_each(F &&f) const {
|
||||
counter_.for_each(f);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
counter_.clear();
|
||||
}
|
||||
|
||||
friend StringBuilder &operator<<(StringBuilder &sb, const NamedPerfCounter &counter) {
|
||||
return sb << counter.counter_;
|
||||
}
|
||||
private:
|
||||
NamedThreadSafeCounter counter_;
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
||||
#define TD_PERF_COUNTER(name) \
|
||||
static auto perf_##name = td::NamedPerfCounter::get_default().get_counter(td::Slice(#name)); \
|
||||
auto scoped_perf_##name = td::NamedPerfCounter::ScopedPerfCounterRef{.perf_counter = perf_##name};
|
||||
|
||||
#define TD_PERF_COUNTER_SINCE(name, since) \
|
||||
static auto perf_##name = td::NamedPerfCounter::get_default().get_counter(td::Slice(#name)); \
|
||||
auto scoped_perf_##name = \
|
||||
td::NamedPerfCounter::ScopedPerfCounterRef{.perf_counter = perf_##name, .started_at_ticks = since};
|
||||
|
|
|
@ -127,4 +127,12 @@ struct Auto {
|
|||
}
|
||||
};
|
||||
|
||||
struct NoCopyOrMove {
|
||||
NoCopyOrMove() = default;
|
||||
NoCopyOrMove(NoCopyOrMove &&) = delete;
|
||||
NoCopyOrMove(const NoCopyOrMove &) = delete;
|
||||
NoCopyOrMove &operator=(NoCopyOrMove &&) = delete;
|
||||
NoCopyOrMove &operator=(const NoCopyOrMove &) = delete;
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
#include "td/utils/logging.h"
|
||||
|
||||
#include "ThreadSafeCounter.h"
|
||||
#include "td/utils/port/Clocks.h"
|
||||
#include "td/utils/port/StdStreams.h"
|
||||
#include "td/utils/port/thread_local.h"
|
||||
|
@ -127,6 +128,9 @@ Logger::~Logger() {
|
|||
slice = MutableCSlice(slice.begin(), slice.begin() + slice.size() - 1);
|
||||
}
|
||||
log_.append(slice, log_level_);
|
||||
|
||||
// put stats here to avoid conflict with PSTRING and PSLICE
|
||||
TD_PERF_COUNTER_SINCE(logger, start_at_);
|
||||
} else {
|
||||
log_.append(as_cslice(), log_level_);
|
||||
}
|
||||
|
@ -301,5 +305,4 @@ ScopedDisableLog::~ScopedDisableLog() {
|
|||
set_verbosity_level(sdl_verbosity);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "td/utils/Slice.h"
|
||||
#include "td/utils/StackAllocator.h"
|
||||
#include "td/utils/StringBuilder.h"
|
||||
#include "td/utils/port/Clocks.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <type_traits>
|
||||
|
@ -251,7 +252,8 @@ class Logger {
|
|||
, log_(log)
|
||||
, sb_(buffer_.as_slice())
|
||||
, options_(options)
|
||||
, log_level_(log_level) {
|
||||
, log_level_(log_level)
|
||||
, start_at_(Clocks::rdtsc()) {
|
||||
}
|
||||
|
||||
Logger(LogInterface &log, const LogOptions &options, int log_level, Slice file_name, int line_num, Slice comment);
|
||||
|
@ -283,6 +285,7 @@ class Logger {
|
|||
StringBuilder sb_;
|
||||
const LogOptions &options_;
|
||||
int log_level_;
|
||||
td::uint64 start_at_;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
@ -346,5 +349,4 @@ class TsLog : public LogInterface {
|
|||
lock_.clear(std::memory_order_release);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
#include <ctime>
|
||||
|
||||
namespace td {
|
||||
int64 Clocks::monotonic_nano() {
|
||||
auto duration = std::chrono::steady_clock::now().time_since_epoch();
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
|
||||
}
|
||||
|
||||
double Clocks::monotonic() {
|
||||
// TODO write system specific functions, because std::chrono::steady_clock is steady only under Windows
|
||||
|
|
|
@ -17,15 +17,89 @@
|
|||
Copyright 2017-2020 Telegram Systems LLP
|
||||
*/
|
||||
#pragma once
|
||||
#include "td/utils/int_types.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
struct Clocks {
|
||||
static int64 monotonic_nano();
|
||||
|
||||
static double monotonic();
|
||||
|
||||
static double system();
|
||||
|
||||
static int tz_offset();
|
||||
|
||||
#if defined(__i386__) or defined(__M_IX86)
|
||||
static uint64 rdtsc() {
|
||||
unsigned long long int x;
|
||||
__asm__ volatile("rdtsc" : "=A"(x));
|
||||
return x;
|
||||
}
|
||||
|
||||
static constexpr uint64 rdtsc_frequency() {
|
||||
return 2000'000'000;
|
||||
}
|
||||
|
||||
static constexpr double ticks_per_second() {
|
||||
return 2e9;
|
||||
}
|
||||
|
||||
static constexpr double inv_ticks_per_second() {
|
||||
return 0.5e-9;
|
||||
}
|
||||
#elif defined(__x86_64__) or defined(__M_X64)
|
||||
static uint64 rdtsc() {
|
||||
unsigned hi, lo;
|
||||
__asm__ __volatile__("rdtsc" : "=a"(lo), "=d"(hi));
|
||||
return ((unsigned long long)lo) | (((unsigned long long)hi) << 32);
|
||||
}
|
||||
static constexpr uint64 rdtsc_frequency() {
|
||||
return 2000'000'000;
|
||||
}
|
||||
|
||||
static constexpr double ticks_per_second() {
|
||||
return 2e9;
|
||||
}
|
||||
|
||||
static constexpr double inv_ticks_per_second() {
|
||||
return 0.5e-9;
|
||||
}
|
||||
#elif defined(__aarch64__) or defined(_M_ARM64)
|
||||
static uint64 rdtsc() {
|
||||
unsigned long long val;
|
||||
asm volatile("mrs %0, cntvct_el0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
static uint64 rdtsc_frequency() {
|
||||
unsigned long long val;
|
||||
asm volatile("mrs %0, cntfrq_el0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static double ticks_per_second() {
|
||||
return static_cast<double>(rdtsc_frequency());
|
||||
}
|
||||
|
||||
static double inv_ticks_per_second() {
|
||||
return 1.0 / static_cast<double>(rdtsc_frequency());
|
||||
}
|
||||
#else
|
||||
static uint64 rdtsc() {
|
||||
return monotonic_nano();
|
||||
}
|
||||
static uint64 rdtsc_frequency() {
|
||||
return 1000'000'000;
|
||||
}
|
||||
|
||||
static double ticks_per_second() {
|
||||
return static_cast<double>(rdtsc_frequency());
|
||||
}
|
||||
|
||||
static double inv_ticks_per_second() {
|
||||
return 1.0 / static_cast<double>(rdtsc_frequency());
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace td
|
||||
|
|
|
@ -58,8 +58,7 @@
|
|||
#define PSAPI_VERSION 1
|
||||
#endif
|
||||
#include <psapi.h>
|
||||
#pragma comment( lib, "psapi.lib" )
|
||||
|
||||
#pragma comment(lib, "psapi.lib")
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -413,7 +412,7 @@ Result<CpuStat> cpu_stat() {
|
|||
#endif
|
||||
}
|
||||
|
||||
Result<uint64> get_total_ram() {
|
||||
Result<TotalMemStat> get_total_mem_stat() {
|
||||
#if TD_LINUX
|
||||
TRY_RESULT(fd, FileFd::open("/proc/meminfo", FileFd::Read));
|
||||
SCOPE_EXIT {
|
||||
|
@ -425,8 +424,10 @@ Result<uint64> get_total_ram() {
|
|||
if (size >= TMEM_SIZE - 1) {
|
||||
return Status::Error("Failed for read /proc/meminfo");
|
||||
}
|
||||
TotalMemStat stat;
|
||||
mem[size] = 0;
|
||||
const char* s = mem;
|
||||
const char *s = mem;
|
||||
size_t got = 0;
|
||||
while (*s) {
|
||||
const char *name_begin = s;
|
||||
while (*s != 0 && *s != '\n') {
|
||||
|
@ -437,18 +438,28 @@ Result<uint64> get_total_ram() {
|
|||
name_end++;
|
||||
}
|
||||
Slice name(name_begin, name_end);
|
||||
td::uint64 *dest = nullptr;
|
||||
if (name == "MemTotal") {
|
||||
dest = &stat.total_ram;
|
||||
} else if (name == "MemAvailable") {
|
||||
dest = &stat.available_ram;
|
||||
}
|
||||
if (dest != nullptr) {
|
||||
Slice value(name_end, s);
|
||||
if (!value.empty() && value[0] == ':') {
|
||||
value.remove_prefix(1);
|
||||
}
|
||||
value = trim(value);
|
||||
value = split(value).first;
|
||||
TRY_RESULT_PREFIX(mem, to_integer_safe<uint64>(value), "Invalid value of MemTotal");
|
||||
TRY_RESULT_PREFIX(mem, to_integer_safe<uint64>(value), PSLICE() << "Invalid value of " << name);
|
||||
if (mem >= 1ULL << (64 - 10)) {
|
||||
return Status::Error("Invalid value of MemTotal");
|
||||
}
|
||||
return mem * 1024;
|
||||
*dest = mem * 1024;
|
||||
got++;
|
||||
if (got == 2) {
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
if (*s == 0) {
|
||||
break;
|
||||
|
|
|
@ -64,6 +64,10 @@ Status update_atime(CSlice path) TD_WARN_UNUSED_RESULT;
|
|||
|
||||
#endif
|
||||
|
||||
Result<uint64> get_total_ram() TD_WARN_UNUSED_RESULT;
|
||||
struct TotalMemStat {
|
||||
uint64 total_ram;
|
||||
uint64 available_ram;
|
||||
};
|
||||
Result<TotalMemStat> get_total_mem_stat() TD_WARN_UNUSED_RESULT;
|
||||
|
||||
} // namespace td
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue