Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Commit

Permalink
quic: further refinement to StatsDebug
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell committed Jan 22, 2020
1 parent 937bd04 commit 1fa54f7
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 96 deletions.
20 changes: 5 additions & 15 deletions src/quic/node_quic_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1347,9 +1347,6 @@ QuicSession::QuicSession(

QuicSession::~QuicSession() {
CHECK(!Ngtcp2CallbackScope::InNgtcp2CallbackScope(this));
StatsDebug stats_debug(this);
Debug(this, "Destroyed. %s", stats_debug.ToString().c_str());

crypto_context_->Cancel();
connection_.reset();

Expand All @@ -1359,18 +1356,11 @@ QuicSession::~QuicSession() {
RemoveListener(listener_);
}

std::string QuicSession::StatsDebug::ToString() {
#define V(_, name, label) \
" "## label + ": " + \
std::to_string(session_->GetStat(&QuicSessionStats::name)) + "\n"

std::string out = "Statistics:\n";
out += " Duration: " +
std::to_string(uv_hrtime() -
session_->GetStat(&QuicSessionStats::created_at)) + "\n" +
SESSION_STATS(V);
return out;

void StatsBase<QuicSessionStats, QuicSession>::StatsDebug::ToString(
StatsBase<QuicSessionStats, QuicSession>::AddField add_field) const {
#define V(_n, name, label) \
add_field(label, ptr->GetStat(&QuicSessionStats::name));
SESSION_STATS(V)
#undef V
}

Expand Down
11 changes: 1 addition & 10 deletions src/quic/node_quic_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ class QuicApplication : public MemoryRetainer {
// a QuicSession object.
class QuicSession : public AsyncWrap,
public mem::NgLibMemoryManager<QuicSession, ngtcp2_mem>,
public StatsBase<QuicSessionStats> {
public StatsBase<QuicSessionStats, QuicSession> {
public:
// The default preferred address strategy is to ignore it
static void IgnorePreferredAddressStrategy(
Expand Down Expand Up @@ -1423,15 +1423,6 @@ class QuicSession : public AsyncWrap,

static const ngtcp2_conn_callbacks callbacks[2];

class StatsDebug {
public:
StatsDebug(QuicSession* session) : session_(session) {}
std::string ToString();
private:
QuicSession* session_;
};


friend class QuicCryptoContext;
friend class QuicSessionListener;
friend class JSQuicSessionListener;
Expand Down
19 changes: 5 additions & 14 deletions src/quic/node_quic_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,26 +285,17 @@ QuicSocket::QuicSocket(

QuicSocket::~QuicSocket() {
uint64_t now = uv_hrtime();
StatsDebug stats_debug(this);
Debug(this, "Destroyed. %s", stats_debug.ToString().c_str());
QuicSocketListener* listener = listener_;
listener_->OnDestroy();
if (listener == listener_)
RemoveListener(listener_);
}

std::string QuicSocket::StatsDebug::ToString() {
#define V(_, name, label) \
" "## label + ": " + \
std::to_string(socket_->GetStat(&QuicSocketStats::name)) + "\n"

std::string out = "Statistics:\n";
out += " Duration: " +
std::to_string(uv_hrtime() -
socket_->GetStat(&QuicSocketStats::created_at)) + "\n" +
SOCKET_STATS(V);
return out;

void StatsBase<QuicSocketStats, QuicSocket>::StatsDebug::ToString(
StatsBase<QuicSocketStats, QuicSocket>::AddField add_field) const {
#define V(_n, name, label) \
add_field(label, ptr->GetStat(&QuicSocketStats::name));
SOCKET_STATS(V)
#undef V
}

Expand Down
10 changes: 1 addition & 9 deletions src/quic/node_quic_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ class QuicEndpoint : public BaseObject,
class QuicSocket : public AsyncWrap,
public QuicEndpointListener,
public mem::NgLibMemoryManager<QuicSocket, ngtcp2_mem>,
public StatsBase<QuicSocketStats> {
public StatsBase<QuicSocketStats, QuicSocket> {
public:
static void Initialize(
Environment* env,
Expand Down Expand Up @@ -531,14 +531,6 @@ class QuicSocket : public AsyncWrap,

SendWrap* last_created_send_wrap_ = nullptr;

class StatsDebug {
public:
StatsDebug(QuicSocket* socket) : socket_(socket) {}
std::string ToString();
private:
QuicSocket* socket_;
};

friend class QuicSocketListener;
};

Expand Down
2 changes: 1 addition & 1 deletion src/quic/node_quic_stream-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ void QuicStream::Unschedule() {
stream_queue_.Remove();
}

std::string QuicHeader::ToString() {
std::string QuicHeader::ToString() const {
return name() + " = " + value();
}

Expand Down
22 changes: 6 additions & 16 deletions src/quic/node_quic_stream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,13 @@ QuicStream::QuicStream(
IncrementStat(&QuicStreamStats::max_offset, params.initial_max_data);
}

QuicStream::~QuicStream() {
StatsDebug stats_debug(this);
Debug(this, "Destroyed. %s", stats_debug.ToString().c_str());
}

std::string QuicStream::StatsDebug::ToString() {
#define V(_, name, label) \
" "## label + ": " + \
std::to_string(stream_->GetStat(&QuicStreamStats::name)) + "\n"

std::string out = "Statistics:\n";
out += " Duration: " +
std::to_string(uv_hrtime() -
stream_->GetStat(&QuicStreamStats::created_at)) + "\n" +
STREAM_STATS(V);
return out;
QuicStream::~QuicStream() {}

void StatsBase<QuicStreamStats, QuicStream>::StatsDebug::ToString(
StatsBase<QuicSocketStats, QuicSocket>::AddField add_field) const {
#define V(_n, name, label) \
add_field(label, ptr->GetStat(&QuicStreamStats::name));
STREAM_STATS(V)
#undef V
}

Expand Down
15 changes: 3 additions & 12 deletions src/quic/node_quic_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ struct QuicStreamStats {
// per stream must create a specialization of the Header class.
class QuicHeader : public MemoryRetainer {
public:
QuicHeader() {}

QuicHeader() = default;
virtual ~QuicHeader() {}
virtual v8::MaybeLocal<v8::String> GetName(QuicApplication* app) const = 0;
virtual v8::MaybeLocal<v8::String> GetValue(QuicApplication* app) const = 0;
Expand All @@ -84,7 +83,7 @@ class QuicHeader : public MemoryRetainer {
// (including the name and value)
virtual size_t length() const = 0;

inline std::string ToString();
inline std::string ToString() const;
};

enum QuicStreamStates : uint32_t {
Expand Down Expand Up @@ -198,7 +197,7 @@ enum QuicStreamOrigin {
class QuicStream : public AsyncWrap,
public bob::SourceImpl<ngtcp2_vec>,
public StreamBase,
public StatsBase<QuicStreamStats> {
public StatsBase<QuicStreamStats, QuicStream> {
public:
static void Initialize(
Environment* env,
Expand Down Expand Up @@ -381,14 +380,6 @@ class QuicStream : public AsyncWrap,

ListNode<QuicStream> stream_queue_;

class StatsDebug {
public:
StatsDebug(QuicStream* stream) : stream_(stream) {}
std::string ToString();
private:
QuicStream* stream_;
};

public:
// Linked List of QuicStream objects
using Queue = ListHead<QuicStream, &QuicStream::stream_queue_>;
Expand Down
58 changes: 40 additions & 18 deletions src/quic/node_quic_util-inl.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef SRC_QUIC_NODE_QUIC_UTIL_INL_H_
#define SRC_QUIC_NODE_QUIC_UTIL_INL_H_

#include "debug_utils.h"
#include "node_internals.h"
#include "node_quic_util.h"
#include "memory_tracker-inl.h"
Expand Down Expand Up @@ -317,8 +318,8 @@ bool StatelessResetToken::Compare::operator()(
NGTCP2_STATELESS_RESET_TOKENLEN) == 0;
}

template <typename T>
StatsBase<T>::StatsBase(
template <typename T, typename Q>
StatsBase<T, Q>::StatsBase(
Environment* env,
v8::Local<v8::Object> wrap,
int options)
Expand Down Expand Up @@ -367,29 +368,29 @@ StatsBase<T>::StatsBase(
}
}

template <typename T>
void StatsBase<T>::IncrementStat(uint64_t T::*member, uint64_t amount) {
template <typename T, typename Q>
void StatsBase<T, Q>::IncrementStat(uint64_t T::*member, uint64_t amount) {
static constexpr uint64_t kMax = std::numeric_limits<uint64_t>::max();
stats_.*member += std::min(amount, kMax - stats_.*member);
}

template <typename T>
void StatsBase<T>::SetStat(uint64_t T::*member, uint64_t value) {
template <typename T, typename Q>
void StatsBase<T, Q>::SetStat(uint64_t T::*member, uint64_t value) {
stats_.*member = value;
}

template <typename T>
void StatsBase<T>::RecordTimestamp(uint64_t T::*member) {
template <typename T, typename Q>
void StatsBase<T, Q>::RecordTimestamp(uint64_t T::*member) {
stats_.*member = uv_hrtime();
}

template <typename T>
uint64_t StatsBase<T>::GetStat(uint64_t T::*member) const {
template <typename T, typename Q>
uint64_t StatsBase<T, Q>::GetStat(uint64_t T::*member) const {
return stats_.*member;
}

template <typename T>
inline void StatsBase<T>::RecordRate(uint64_t T::*member) {
template <typename T, typename Q>
inline void StatsBase<T, Q>::RecordRate(uint64_t T::*member) {
CHECK(rate_);

uint64_t received_at = GetStat(member);
Expand All @@ -399,14 +400,14 @@ inline void StatsBase<T>::RecordRate(uint64_t T::*member) {
SetStat(member, now);
}

template <typename T>
inline void StatsBase<T>::RecordSize(uint64_t val) {
template <typename T, typename Q>
inline void StatsBase<T, Q>::RecordSize(uint64_t val) {
CHECK(size_);
size_->Record(val);
}

template <typename T>
inline void StatsBase<T>::RecordAck(uint64_t T::*member) {
template <typename T, typename Q>
inline void StatsBase<T, Q>::RecordAck(uint64_t T::*member) {
CHECK(ack_);
uint64_t acked_at = GetStat(member);
uint64_t now = uv_hrtime();
Expand All @@ -415,14 +416,35 @@ inline void StatsBase<T>::RecordAck(uint64_t T::*member) {
SetStat(member, now);
}

template <typename T>
void StatsBase<T>::StatsMemoryInfo(MemoryTracker* tracker) const {
template <typename T, typename Q>
void StatsBase<T, Q>::StatsMemoryInfo(MemoryTracker* tracker) const {
tracker->TrackField("stats_buffer", stats_buffer_);
tracker->TrackField("rate_histogram", rate_);
tracker->TrackField("size_histogram", size_);
tracker->TrackField("ack_histogram", ack_);
}

template <typename T, typename Q>
StatsBase<T, Q>::~StatsBase() {
StatsBase<T, Q>::StatsDebug stats_debug(static_cast<Q*>(this));
Debug(static_cast<Q*>(this), "Destroyed. %s", stats_debug.ToString().c_str());
}

template <typename T, typename Q>
std::string StatsBase<T, Q>::StatsDebug::ToString() const {
std::string out = "Statistics:\n";
auto add_field = [&out](const char* name, uint64_t val) {
out += " ";
out += std::string(name);
out += ": ";
out += std::to_string(val);
out += "\n";
};
add_field("Duration", uv_hrtime() - ptr->GetStat(&T::created_at));
ToString(add_field);
return out;
}

template <typename T>
size_t get_length(const T* vec, size_t count) {
CHECK_NOT_NULL(vec);
Expand Down
15 changes: 14 additions & 1 deletion src/quic/node_quic_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ enum QuicErrorFamily : int32_t {

// StatsBase is a utility help for classes (like QuicSession)
// that record performance statistics
template <typename T>
template <typename T, typename Q>
class StatsBase {
public:
enum HistogramOptions {
Expand All @@ -87,6 +87,19 @@ class StatsBase {
v8::Local<v8::Object> wrap,
int options = HistogramOptions::NONE);

inline ~StatsBase();

using AddField = std::function<void(const char*, uint64_t)>;

// The StatsDebug utility is used when StatsBase is destroyed
// to output statistical information.
struct StatsDebug {
Q* ptr;
explicit StatsDebug(Q* ptr_) : ptr(ptr_) {}
std::string ToString() const;
void ToString(AddField add_field) const;
};

protected:
// Increments the given stat field by the given amount
inline void IncrementStat(uint64_t T::*member, uint64_t amount = 1);
Expand Down

0 comments on commit 1fa54f7

Please sign in to comment.