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

Commit 4835a89

Browse files
addaleaxjasnell
authored andcommitted
quic: support memory tracking
Fixes: #59 PR-URL: #145 Reviewed-By: James M Snell <[email protected]>
1 parent 963d54c commit 4835a89

File tree

7 files changed

+200
-8
lines changed

7 files changed

+200
-8
lines changed

src/node_quic_session.cc

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,6 +1883,24 @@ bool QuicSession::UpdateKey() {
18831883
&crypto_ctx_);
18841884
}
18851885

1886+
void QuicSession::MemoryInfo(MemoryTracker* tracker) const {
1887+
tracker->TrackField("alpn", alpn_);
1888+
tracker->TrackField("idle", idle_);
1889+
tracker->TrackField("retransmit", retransmit_);
1890+
tracker->TrackField("rx_secret", rx_secret_);
1891+
tracker->TrackField("tx_secret", tx_secret_);
1892+
tracker->TrackField("sendbuf", sendbuf_);
1893+
tracker->TrackField("handshake", handshake_);
1894+
tracker->TrackField("txbuf", txbuf_);
1895+
tracker->TrackField("peer_handshake", peer_handshake_);
1896+
tracker->TrackField("streams", streams_);
1897+
tracker->TrackField("state", state_);
1898+
tracker->TrackField("crypto_rx_ack", crypto_rx_ack_);
1899+
tracker->TrackField("crypto_handshake_rate", crypto_handshake_rate_);
1900+
tracker->TrackField("stats_buffer", stats_buffer_);
1901+
tracker->TrackField("recovery_stats_buffer", recovery_stats_buffer_);
1902+
tracker->TrackFieldWithSize("current_ngtcp2_memory", current_ngtcp2_memory_);
1903+
}
18861904

18871905
// QuicServerSession
18881906
QuicServerSession::InitialPacketResult QuicServerSession::Accept(
@@ -2376,6 +2394,11 @@ int QuicServerSession::VerifyPeerIdentity(const char* hostname) {
23762394
return VerifyPeerCertificate(ssl());
23772395
}
23782396

2397+
void QuicServerSession::MemoryInfo(MemoryTracker* tracker) const {
2398+
QuicSession::MemoryInfo(tracker);
2399+
tracker->TrackField("conn_closebuf", conn_closebuf_);
2400+
tracker->TrackField("ocsp_response", ocsp_response_);
2401+
}
23792402

23802403
// QuicClientSession
23812404

@@ -2888,6 +2911,11 @@ int QuicClientSession::VerifyPeerIdentity(const char* hostname) {
28882911
return 0;
28892912
}
28902913

2914+
void QuicClientSession::MemoryInfo(MemoryTracker* tracker) const {
2915+
QuicSession::MemoryInfo(tracker);
2916+
tracker->TrackField("hostname", hostname_);
2917+
}
2918+
28912919
// Static ngtcp2 callbacks are registered when ngtcp2 when a new ngtcp2_conn is
28922920
// created. These are static functions that, for the most part, simply defer to
28932921
// a QuicSession instance that is passed through as user_data.

src/node_quic_session.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ class QuicSession : public AsyncWrap,
364364
QuicSession* session_;
365365
};
366366

367+
void MemoryInfo(MemoryTracker* tracker) const override;
368+
367369
private:
368370
// Returns true if the QuicSession has entered the
369371
// closing period following a call to ImmediateClose.
@@ -1063,7 +1065,8 @@ class QuicServerSession : public QuicSession {
10631065
const ngtcp2_cid* rcid() const { return &rcid_; }
10641066
ngtcp2_cid* pscid() { return &pscid_; }
10651067

1066-
void MemoryInfo(MemoryTracker* tracker) const override {}
1068+
void MemoryInfo(MemoryTracker* tracker) const override;
1069+
10671070
SET_MEMORY_INFO_NAME(QuicServerSession)
10681071
SET_SELF_SIZE(QuicServerSession)
10691072

@@ -1168,7 +1171,8 @@ class QuicClientSession : public QuicSession {
11681171

11691172
bool SendConnectionClose() override;
11701173

1171-
void MemoryInfo(MemoryTracker* tracker) const override {}
1174+
void MemoryInfo(MemoryTracker* tracker) const override;
1175+
11721176
SET_MEMORY_INFO_NAME(QuicClientSession)
11731177
SET_SELF_SIZE(QuicClientSession)
11741178

src/node_quic_socket.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,13 @@ QuicSocket::~QuicSocket() {
120120
}
121121

122122
void QuicSocket::MemoryInfo(MemoryTracker* tracker) const {
123-
// TODO(@jasnell): Implement memory tracking information
123+
tracker->TrackField("sessions", sessions_);
124+
tracker->TrackField("dcid_to_scid", dcid_to_scid_);
125+
tracker->TrackFieldWithSize("addr_counts",
126+
addr_counts_.size() * (sizeof(sockaddr*) + sizeof(size_t)));
127+
tracker->TrackField("validated_addrs", validated_addrs_);
128+
tracker->TrackField("stats_buffer", stats_buffer_);
129+
tracker->TrackFieldWithSize("current_ngtcp2_memory", current_ngtcp2_memory_);
124130
}
125131

126132
void QuicSocket::AddSession(

src/node_quic_stream.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,14 @@ BaseObjectPtr<QuicStream> QuicStream::New(
379379
return stream;
380380
}
381381

382+
void QuicStream::MemoryInfo(MemoryTracker* tracker) const {
383+
tracker->TrackField("buffer", &streambuf_);
384+
tracker->TrackField("data_rx_rate", data_rx_rate_);
385+
tracker->TrackField("data_rx_size", data_rx_size_);
386+
tracker->TrackField("data_rx_ack", data_rx_ack_);
387+
tracker->TrackField("stats_buffer", stats_buffer_);
388+
}
389+
382390
// JavaScript API
383391
namespace {
384392
void QuicStreamGetID(const FunctionCallbackInfo<Value>& args) {

src/node_quic_stream.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,9 +296,7 @@ class QuicStream : public AsyncWrap, public StreamBase {
296296

297297
AsyncWrap* GetAsyncWrap() override { return this; }
298298

299-
void MemoryInfo(MemoryTracker* tracker) const override {
300-
tracker->TrackField("buffer", &streambuf_);
301-
}
299+
void MemoryInfo(MemoryTracker* tracker) const override;
302300

303301
SET_MEMORY_INFO_NAME(QuicStream)
304302
SET_SELF_SIZE(QuicStream)

src/node_quic_util.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ void IncrementStat(
384384
// Simple timer wrapper that is used to implement the internals
385385
// for idle and retransmission timeouts. Call Update to start or
386386
// reset the timer; Stop to halt the timer.
387-
class Timer {
387+
class Timer final : public MemoryRetainer {
388388
public:
389389
explicit Timer(Environment* env, std::function<void()> fn)
390390
: stopped_(false),
@@ -395,7 +395,7 @@ class Timer {
395395
env->AddCleanupHook(CleanupHook, this);
396396
}
397397

398-
~Timer() {
398+
~Timer() override {
399399
env_->RemoveCleanupHook(CleanupHook, this);
400400
}
401401

@@ -423,6 +423,10 @@ class Timer {
423423

424424
static void Free(Timer* timer);
425425

426+
SET_NO_MEMORY_INFO()
427+
SET_MEMORY_INFO_NAME(Timer)
428+
SET_SELF_SIZE(Timer)
429+
426430
private:
427431
static void OnTimeout(uv_timer_t* timer);
428432
static void CleanupHook(void* data);

test/pummel/test-heapdump-quic.js

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Flags: --expose-internals
2+
'use strict';
3+
const common = require('../common');
4+
if (!common.hasQuic)
5+
common.skip('missing quic');
6+
7+
const quic = require('quic');
8+
9+
const { recordState } = require('../common/heap');
10+
const fixtures = require('../common/fixtures');
11+
const key = fixtures.readKey('agent1-key.pem', 'binary');
12+
const cert = fixtures.readKey('agent1-cert.pem', 'binary');
13+
const ca = fixtures.readKey('ca1-cert.pem', 'binary');
14+
15+
{
16+
const state = recordState();
17+
state.validateSnapshotNodes('Node / QuicStream', []);
18+
state.validateSnapshotNodes('Node / QuicSession', []);
19+
state.validateSnapshotNodes('Node / QuicSocket', []);
20+
}
21+
22+
const server = quic.createSocket({ port: 0, validateAddress: true });
23+
24+
server.listen({
25+
key,
26+
cert,
27+
ca,
28+
rejectUnauthorized: false,
29+
maxCryptoBuffer: 4096,
30+
alpn: 'meow'
31+
});
32+
33+
server.on('session', common.mustCall((session) => {
34+
session.on('secure', common.mustCall((servername, alpn, cipher) => {
35+
// eslint-disable-next-line no-unused-vars
36+
const stream = session.openStream({ halfOpen: false });
37+
38+
const state = recordState();
39+
40+
state.validateSnapshotNodes('Node / QuicSocket', [
41+
{
42+
children: [
43+
{ node_name: 'QuicSocket', edge_name: 'wrapped' },
44+
{ node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
45+
{ node_name: 'Node / sessions', edge_name: 'sessions' },
46+
{ node_name: 'Node / dcid_to_scid', edge_name: 'dcid_to_scid' },
47+
]
48+
}
49+
], { loose: true });
50+
51+
state.validateSnapshotNodes('Node / QuicStream', [
52+
{
53+
children: [
54+
{ node_name: 'QuicStream', edge_name: 'wrapped' },
55+
{ node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
56+
{ node_name: 'Node / QuicBuffer', edge_name: 'buffer' },
57+
{ node_name: 'Node / HistogramBase', edge_name: 'data_rx_rate' },
58+
{ node_name: 'Node / HistogramBase', edge_name: 'data_rx_size' },
59+
{ node_name: 'Node / HistogramBase', edge_name: 'data_rx_ack' }
60+
]
61+
}
62+
], { loose: true });
63+
64+
state.validateSnapshotNodes('Node / QuicBuffer', [
65+
{
66+
children: [
67+
{ node_name: 'Node / length', edge_name: 'length' }
68+
]
69+
}
70+
], { loose: true });
71+
72+
state.validateSnapshotNodes('Node / QuicServerSession', [
73+
{
74+
children: [
75+
{ node_name: 'QuicServerSession', edge_name: 'wrapped' },
76+
{ node_name: 'Node / rx_secret', edge_name: 'rx_secret' },
77+
{ node_name: 'Node / tx_secret', edge_name: 'tx_secret' },
78+
{ node_name: 'Node / HistogramBase', edge_name: 'crypto_rx_ack' },
79+
{ node_name: 'Node / HistogramBase',
80+
edge_name: 'crypto_handshake_rate' },
81+
{ node_name: 'Node / Timer', edge_name: 'retransmit' },
82+
{ node_name: 'Node / Timer', edge_name: 'idle' },
83+
{ node_name: 'Node / QuicBuffer', edge_name: 'sendbuf' },
84+
{ node_name: 'Node / QuicBuffer', edge_name: 'txbuf' },
85+
{ node_name: 'Node / peer_handshake', edge_name: 'peer_handshake' },
86+
{ node_name: 'Float64Array', edge_name: 'recovery_stats_buffer' },
87+
{ node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
88+
{ node_name: 'Node / current_ngtcp2_memory',
89+
edge_name: 'current_ngtcp2_memory' },
90+
{ node_name: 'Node / streams', edge_name: 'streams' },
91+
{ node_name: 'Node / QuicBuffer', edge_name: 'handshake' },
92+
{ node_name: 'Node / std::basic_string', edge_name: 'alpn' },
93+
{ node_name: 'Float64Array', edge_name: 'state' },
94+
]
95+
}
96+
], { loose: true });
97+
98+
state.validateSnapshotNodes('Node / QuicClientSession', [
99+
{
100+
children: [
101+
{ node_name: 'QuicClientSession', edge_name: 'wrapped' },
102+
{ node_name: 'Node / rx_secret', edge_name: 'rx_secret' },
103+
{ node_name: 'Node / tx_secret', edge_name: 'tx_secret' },
104+
{ node_name: 'Node / HistogramBase', edge_name: 'crypto_rx_ack' },
105+
{ node_name: 'Node / HistogramBase',
106+
edge_name: 'crypto_handshake_rate' },
107+
{ node_name: 'Node / Timer', edge_name: 'retransmit' },
108+
{ node_name: 'Node / Timer', edge_name: 'idle' },
109+
{ node_name: 'Node / QuicBuffer', edge_name: 'sendbuf' },
110+
{ node_name: 'Node / QuicBuffer', edge_name: 'txbuf' },
111+
{ node_name: 'Node / peer_handshake', edge_name: 'peer_handshake' },
112+
{ node_name: 'Float64Array', edge_name: 'recovery_stats_buffer' },
113+
{ node_name: 'BigUint64Array', edge_name: 'stats_buffer' },
114+
{ node_name: 'Node / current_ngtcp2_memory',
115+
edge_name: 'current_ngtcp2_memory' },
116+
{ node_name: 'Node / QuicBuffer', edge_name: 'handshake' },
117+
{ node_name: 'Node / std::basic_string', edge_name: 'alpn' },
118+
{ node_name: 'Node / std::basic_string', edge_name: 'hostname' },
119+
{ node_name: 'Float64Array', edge_name: 'state' },
120+
]
121+
}
122+
], { loose: true });
123+
124+
session.destroy();
125+
server.close();
126+
}));
127+
}));
128+
129+
server.on('ready', common.mustCall(() => {
130+
const client = quic.createSocket({
131+
port: 0,
132+
client: {
133+
key,
134+
cert,
135+
ca,
136+
alpn: 'meow'
137+
}
138+
});
139+
140+
client.connect({
141+
address: 'localhost',
142+
port: server.address.port
143+
}).on('close', common.mustCall(() => client.close()));
144+
}));

0 commit comments

Comments
 (0)