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

Commit 5cee239

Browse files
committed
quic: use backing store for StatsBase
1 parent 6e903f5 commit 5cee239

File tree

3 files changed

+50
-59
lines changed

3 files changed

+50
-59
lines changed

src/aliased_buffer.h

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,31 +32,6 @@ template <class NativeT,
3232
typename = std::enable_if_t<std::is_scalar<NativeT>::value>>
3333
class AliasedBufferBase {
3434
public:
35-
/**
36-
* Create an AliasedBufferBase over an existing buffer
37-
*/
38-
AliasedBufferBase(
39-
v8::Isolate* isolate,
40-
const size_t count,
41-
NativeT* buffer) :
42-
isolate_(isolate),
43-
count_(count),
44-
byte_offset_(0),
45-
buffer_(buffer) {
46-
CHECK_GT(count, 0);
47-
const v8::HandleScope handle_scope(isolate_);
48-
const size_t size_in_bytes =
49-
MultiplyWithOverflowCheck(sizeof(NativeT), count);
50-
v8::Local<v8::ArrayBuffer> ab =
51-
v8::ArrayBuffer::New(
52-
isolate_,
53-
buffer,
54-
size_in_bytes);
55-
56-
v8::Local<V8T> js_array = V8T::New(ab, byte_offset_, count);
57-
js_array_ = v8::Global<V8T>(isolate, js_array);
58-
}
59-
6035
AliasedBufferBase(v8::Isolate* isolate, const size_t count)
6136
: isolate_(isolate), count_(count), byte_offset_(0) {
6237
CHECK_GT(count, 0);
@@ -199,6 +174,14 @@ class AliasedBufferBase {
199174
return buffer_;
200175
}
201176

177+
/**
178+
* Get the underlying native buffer as a cast to T.
179+
**/
180+
template <typename T>
181+
inline T* GetNativeBuffer() {
182+
return reinterpret_cast<T*>(&buffer_);
183+
}
184+
202185
/**
203186
* Synonym for GetBuffer()
204187
*/

src/quic/node_quic_util-inl.h

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -324,23 +324,29 @@ template <typename T>
324324
StatsBase<T>::StatsBase(
325325
Environment* env,
326326
v8::Local<v8::Object> wrap,
327-
int options)
328-
: stats_buffer_(
329-
env->isolate(),
330-
sizeof(typename T::Stats) / sizeof(uint64_t),
331-
reinterpret_cast<uint64_t*>(&stats_)) {
327+
int options) {
332328
static constexpr uint64_t kMax = std::numeric_limits<int64_t>::max();
333-
stats_.created_at = uv_hrtime();
334329

335-
// TODO(@jasnell): The follow are checks instead of handling
336-
// the error. Before this code moves out of experimental,
337-
// these should be change to properly handle the error.
338-
339-
wrap->DefineOwnProperty(
330+
// Create the backing store for the statistics
331+
size_t size = sizeof(Stats);
332+
size_t count = size / sizeof(uint64_t);
333+
stats_store_ = v8::ArrayBuffer::NewBackingStore(env->isolate(), size);
334+
stats_ = new (stats_store_->Data()) Stats;
335+
336+
DCHECK_NOT_NULL(stats_);
337+
stats_->created_at = uv_hrtime();
338+
339+
// The stats buffer is exposed as a BigUint64Array on
340+
// the JavaScript side to allow statistics to be monitored.
341+
v8::Local<v8::ArrayBuffer> stats_buffer =
342+
v8::ArrayBuffer::New(env->isolate(), stats_store_);
343+
v8::Local<v8::BigUint64Array> stats_array =
344+
v8::BigUint64Array::New(stats_buffer, 0, count);
345+
USE(wrap->DefineOwnProperty(
340346
env->context(),
341347
env->stats_string(),
342-
stats_buffer_.GetJSArray(),
343-
v8::PropertyAttribute::ReadOnly).Check();
348+
stats_array,
349+
v8::PropertyAttribute::ReadOnly));
344350

345351
if (options & HistogramOptions::ACK) {
346352
ack_ = HistogramBase::New(env, 1, kMax);
@@ -371,28 +377,28 @@ StatsBase<T>::StatsBase(
371377
}
372378

373379
template <typename T>
374-
void StatsBase<T>::IncrementStat(uint64_t T::Stats::*member, uint64_t amount) {
380+
void StatsBase<T>::IncrementStat(uint64_t Stats::*member, uint64_t amount) {
375381
static constexpr uint64_t kMax = std::numeric_limits<uint64_t>::max();
376-
stats_.*member += std::min(amount, kMax - stats_.*member);
382+
stats_->*member += std::min(amount, kMax - stats_->*member);
377383
}
378384

379385
template <typename T>
380-
void StatsBase<T>::SetStat(uint64_t T::Stats::*member, uint64_t value) {
381-
stats_.*member = value;
386+
void StatsBase<T>::SetStat(uint64_t Stats::*member, uint64_t value) {
387+
stats_->*member = value;
382388
}
383389

384390
template <typename T>
385-
void StatsBase<T>::RecordTimestamp(uint64_t T::Stats::*member) {
386-
stats_.*member = uv_hrtime();
391+
void StatsBase<T>::RecordTimestamp(uint64_t Stats::*member) {
392+
stats_->*member = uv_hrtime();
387393
}
388394

389395
template <typename T>
390-
uint64_t StatsBase<T>::GetStat(uint64_t T::Stats::*member) const {
391-
return stats_.*member;
396+
uint64_t StatsBase<T>::GetStat(uint64_t Stats::*member) const {
397+
return stats_->*member;
392398
}
393399

394400
template <typename T>
395-
inline void StatsBase<T>::RecordRate(uint64_t T::Stats::*member) {
401+
inline void StatsBase<T>::RecordRate(uint64_t Stats::*member) {
396402
CHECK(rate_);
397403
uint64_t received_at = GetStat(member);
398404
uint64_t now = uv_hrtime();
@@ -408,7 +414,7 @@ inline void StatsBase<T>::RecordSize(uint64_t val) {
408414
}
409415

410416
template <typename T>
411-
inline void StatsBase<T>::RecordAck(uint64_t T::Stats::*member) {
417+
inline void StatsBase<T>::RecordAck(uint64_t Stats::*member) {
412418
CHECK(ack_);
413419
uint64_t acked_at = GetStat(member);
414420
uint64_t now = uv_hrtime();
@@ -419,7 +425,7 @@ inline void StatsBase<T>::RecordAck(uint64_t T::Stats::*member) {
419425

420426
template <typename T>
421427
void StatsBase<T>::StatsMemoryInfo(MemoryTracker* tracker) const {
422-
tracker->TrackField("stats_buffer", stats_buffer_);
428+
tracker->TrackField("stats_store", stats_store_);
423429
tracker->TrackField("rate_histogram", rate_);
424430
tracker->TrackField("size_histogram", size_);
425431
tracker->TrackField("ack_histogram", ack_);
@@ -441,7 +447,7 @@ std::string StatsBase<T>::StatsDebug::ToString() const {
441447
out += std::to_string(val);
442448
out += "\n";
443449
};
444-
add_field("Duration", uv_hrtime() - ptr->GetStat(&T::Stats::created_at));
450+
add_field("Duration", uv_hrtime() - ptr->GetStat(&Stats::created_at));
445451
T::ToString(*ptr, add_field);
446452
return out;
447453
}

src/quic/node_quic_util.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ struct StatsTraits {
109109
template <typename T>
110110
class StatsBase {
111111
public:
112+
typedef typename T::Stats Stats;
113+
112114
// A StatsBase instance may have one of three histogram
113115
// instances. One that records rate of data flow, one
114116
// that records size of data chunk, and one that records
@@ -127,7 +129,7 @@ class StatsBase {
127129
v8::Local<v8::Object> wrap,
128130
int options = HistogramOptions::NONE);
129131

130-
inline ~StatsBase() = default;
132+
inline ~StatsBase() { if (stats_ != nullptr) stats_->~Stats(); }
131133

132134
// The StatsDebug utility is used when StatsBase is destroyed
133135
// to output statistical information to Debug. It is designed
@@ -141,40 +143,40 @@ class StatsBase {
141143

142144
// Increments the given stat field by the given amount or 1 if
143145
// no amount is specified.
144-
inline void IncrementStat(uint64_t T::Stats::*member, uint64_t amount = 1);
146+
inline void IncrementStat(uint64_t Stats::*member, uint64_t amount = 1);
145147

146148
// Sets an entirely new value for the given stat field
147-
inline void SetStat(uint64_t T::Stats::*member, uint64_t value);
149+
inline void SetStat(uint64_t Stats::*member, uint64_t value);
148150

149151
// Sets the given stat field to the current uv_hrtime()
150-
inline void RecordTimestamp(uint64_t T::Stats::*member);
152+
inline void RecordTimestamp(uint64_t Stats::*member);
151153

152154
// Gets the current value of the given stat field
153-
inline uint64_t GetStat(uint64_t T::Stats::*member) const;
155+
inline uint64_t GetStat(uint64_t Stats::*member) const;
154156

155157
// If the rate histogram is used, records the time elapsed
156158
// between now and the timestamp specified by the member
157159
// field.
158-
inline void RecordRate(uint64_t T::Stats::*member);
160+
inline void RecordRate(uint64_t Stats::*member);
159161

160162
// If the size histogram is used, records the given size.
161163
inline void RecordSize(uint64_t val);
162164

163165
// If the ack rate histogram is used, records the time
164166
// elapsed between now and the timestamp specified by
165167
// the member field.
166-
inline void RecordAck(uint64_t T::Stats::*member);
168+
inline void RecordAck(uint64_t Stats::*member);
167169

168170
inline void StatsMemoryInfo(MemoryTracker* tracker) const;
169171

170172
inline void DebugStats();
171173

172174
private:
173-
typename T::Stats stats_{};
174175
BaseObjectPtr<HistogramBase> rate_;
175176
BaseObjectPtr<HistogramBase> size_;
176177
BaseObjectPtr<HistogramBase> ack_;
177-
AliasedBigUint64Array stats_buffer_;
178+
std::shared_ptr<v8::BackingStore> stats_store_;
179+
Stats* stats_ = nullptr;
178180
};
179181

180182
// PreferredAddress is a helper class used only when a client QuicSession

0 commit comments

Comments
 (0)