Skip to content

Commit 8a0d101

Browse files
committed
http2: use per-environment buffers
As discussed in the review for #14239, these buffers should be per-Environment rather than static. PR-URL: #14744 Reviewed-By: James M Snell <[email protected]>
1 parent 59d1d56 commit 8a0d101

File tree

5 files changed

+60
-63
lines changed

5 files changed

+60
-63
lines changed

lib/internal/http2/core.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ const kType = Symbol('type');
7373
const kDefaultSocketTimeout = 2 * 60 * 1000;
7474
const kRenegTest = /TLS session renegotiation disabled for this socket/;
7575

76-
const paddingBuffer = new Uint32Array(binding.paddingArrayBuffer);
76+
const { paddingBuffer } = binding;
7777

7878
const {
7979
NGHTTP2_CANCEL,

lib/internal/http2/util.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,14 @@ const kNoPayloadMethods = new Set([
114114
// the native side with values that are filled in on demand, the js code then
115115
// reads those values out. The set of IDX constants that follow identify the
116116
// relevant data positions within these buffers.
117-
const settingsBuffer = new Uint32Array(binding.settingsArrayBuffer);
118-
const optionsBuffer = new Uint32Array(binding.optionsArrayBuffer);
117+
const { settingsBuffer, optionsBuffer } = binding;
119118

120119
// Note that Float64Array is used here because there is no Int64Array available
121120
// and these deal with numbers that can be beyond the range of Uint32 and Int32.
122121
// The values set on the native side will always be integers. This is not a
123122
// unique example of this, this pattern can be found in use in other parts of
124123
// Node.js core as a performance optimization.
125-
const sessionState = new Float64Array(binding.sessionStateArrayBuffer);
126-
const streamState = new Float64Array(binding.streamStateArrayBuffer);
124+
const { sessionState, streamState } = binding;
127125

128126
const IDX_SETTINGS_HEADER_TABLE_SIZE = 0;
129127
const IDX_SETTINGS_ENABLE_PUSH = 1;

src/env-inl.h

+10
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ inline Environment::~Environment() {
329329
delete[] heap_statistics_buffer_;
330330
delete[] heap_space_statistics_buffer_;
331331
delete[] http_parser_buffer_;
332+
free(http2_state_buffer_);
332333
}
333334

334335
inline v8::Isolate* Environment::isolate() const {
@@ -478,6 +479,15 @@ inline void Environment::set_http_parser_buffer(char* buffer) {
478479
http_parser_buffer_ = buffer;
479480
}
480481

482+
inline http2::http2_state* Environment::http2_state_buffer() const {
483+
return http2_state_buffer_;
484+
}
485+
486+
inline void Environment::set_http2_state_buffer(http2::http2_state* buffer) {
487+
CHECK_EQ(http2_state_buffer_, nullptr); // Should be set only once.
488+
http2_state_buffer_ = buffer;
489+
}
490+
481491
inline double* Environment::fs_stats_field_array() const {
482492
return fs_stats_field_array_;
483493
}

src/env.h

+8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343

4444
namespace node {
4545

46+
namespace http2 {
47+
struct http2_state;
48+
}
49+
4650
// Pick an index that's hopefully out of the way when we're embedded inside
4751
// another application. Performance-wise or memory-wise it doesn't matter:
4852
// Context::SetAlignedPointerInEmbedderData() is backed by a FixedArray,
@@ -599,6 +603,9 @@ class Environment {
599603
inline char* http_parser_buffer() const;
600604
inline void set_http_parser_buffer(char* buffer);
601605

606+
inline http2::http2_state* http2_state_buffer() const;
607+
inline void set_http2_state_buffer(http2::http2_state* buffer);
608+
602609
inline double* fs_stats_field_array() const;
603610
inline void set_fs_stats_field_array(double* fields);
604611

@@ -705,6 +712,7 @@ class Environment {
705712
double* heap_space_statistics_buffer_ = nullptr;
706713

707714
char* http_parser_buffer_;
715+
http2::http2_state* http2_state_buffer_ = nullptr;
708716

709717
double* fs_stats_field_array_;
710718

src/node_http2.cc

+39-58
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ namespace node {
77
using v8::ArrayBuffer;
88
using v8::Boolean;
99
using v8::Context;
10+
using v8::Float64Array;
1011
using v8::Function;
1112
using v8::Integer;
1213
using v8::String;
1314
using v8::Uint32;
15+
using v8::Uint32Array;
1416
using v8::Undefined;
1517

1618
namespace http2 {
@@ -57,27 +59,18 @@ enum Http2OptionsIndex {
5759
IDX_OPTIONS_FLAGS
5860
};
5961

60-
static uint32_t http2_padding_buffer[3];
61-
static uint32_t http2_options_buffer[IDX_OPTIONS_FLAGS + 1];
62-
static uint32_t http2_settings_buffer[IDX_SETTINGS_COUNT + 1];
63-
static double http2_session_state_buffer[IDX_SESSION_STATE_COUNT];
64-
static double http2_stream_state_buffer[IDX_STREAM_STATE_COUNT];
65-
66-
static const size_t http2_options_buffer_byte_length =
67-
sizeof(http2_options_buffer) * (IDX_OPTIONS_FLAGS + 1);
68-
static const size_t http2_settings_buffer_byte_length =
69-
sizeof(http2_settings_buffer) * (IDX_SETTINGS_COUNT + 1);
70-
static const size_t http2_padding_buffer_byte_length =
71-
sizeof(http2_padding_buffer) * 3;
72-
static const size_t http2_stream_state_buffer_byte_length =
73-
sizeof(http2_stream_state_buffer) * IDX_STREAM_STATE_COUNT;
74-
static const size_t http2_session_state_buffer_byte_length =
75-
sizeof(http2_session_state_buffer) * IDX_SESSION_STATE_COUNT;
62+
struct http2_state {
63+
uint32_t padding_buffer[3];
64+
uint32_t options_buffer[IDX_OPTIONS_FLAGS + 1];
65+
uint32_t settings_buffer[IDX_SETTINGS_COUNT + 1];
66+
double session_state_buffer[IDX_SESSION_STATE_COUNT];
67+
double stream_state_buffer[IDX_STREAM_STATE_COUNT];
68+
};
7669

7770
Http2Options::Http2Options(Environment* env) {
7871
nghttp2_option_new(&options_);
7972

80-
uint32_t* buffer = http2_options_buffer;
73+
uint32_t* buffer = env->http2_state_buffer()->options_buffer;
8174
uint32_t flags = buffer[IDX_OPTIONS_FLAGS];
8275

8376
if (flags & (1 << IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE)) {
@@ -126,7 +119,7 @@ ssize_t Http2Session::OnCallbackPadding(size_t frameLen,
126119
Context::Scope context_scope(context);
127120

128121
if (object()->Has(context, env()->ongetpadding_string()).FromJust()) {
129-
uint32_t* buffer = http2_padding_buffer;
122+
uint32_t* buffer = env()->http2_state_buffer()->padding_buffer;
130123
buffer[0] = frameLen;
131124
buffer[1] = maxPayloadLen;
132125
MakeCallback(env()->ongetpadding_string(), 0, nullptr);
@@ -167,7 +160,7 @@ void PackSettings(const FunctionCallbackInfo<Value>& args) {
167160
std::vector<nghttp2_settings_entry> entries;
168161
entries.reserve(6);
169162

170-
uint32_t* buffer = http2_settings_buffer;
163+
uint32_t* buffer = env->http2_state_buffer()->settings_buffer;
171164
uint32_t flags = buffer[IDX_SETTINGS_COUNT];
172165

173166
if (flags & (1 << IDX_SETTINGS_HEADER_TABLE_SIZE)) {
@@ -226,7 +219,8 @@ void PackSettings(const FunctionCallbackInfo<Value>& args) {
226219
// Used to fill in the spec defined initial values for each setting.
227220
void RefreshDefaultSettings(const FunctionCallbackInfo<Value>& args) {
228221
DEBUG_HTTP2("Http2Session: refreshing default settings\n");
229-
uint32_t* buffer = http2_settings_buffer;
222+
Environment* env = Environment::GetCurrent(args);
223+
uint32_t* buffer = env->http2_state_buffer()->settings_buffer;
230224
buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] =
231225
DEFAULT_SETTINGS_HEADER_TABLE_SIZE;
232226
buffer[IDX_SETTINGS_ENABLE_PUSH] =
@@ -245,13 +239,14 @@ void RefreshDefaultSettings(const FunctionCallbackInfo<Value>& args) {
245239
template <get_setting fn>
246240
void RefreshSettings(const FunctionCallbackInfo<Value>& args) {
247241
DEBUG_HTTP2("Http2Session: refreshing settings for session\n");
242+
Environment* env = Environment::GetCurrent(args);
248243
CHECK_EQ(args.Length(), 1);
249244
CHECK(args[0]->IsObject());
250245
Http2Session* session;
251246
ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>());
252247
nghttp2_session* s = session->session();
253248

254-
uint32_t* buffer = http2_settings_buffer;
249+
uint32_t* buffer = env->http2_state_buffer()->settings_buffer;
255250
buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] =
256251
fn(s, NGHTTP2_SETTINGS_HEADER_TABLE_SIZE);
257252
buffer[IDX_SETTINGS_MAX_CONCURRENT_STREAMS] =
@@ -269,9 +264,10 @@ void RefreshSettings(const FunctionCallbackInfo<Value>& args) {
269264
// Used to fill in the spec defined initial values for each setting.
270265
void RefreshSessionState(const FunctionCallbackInfo<Value>& args) {
271266
DEBUG_HTTP2("Http2Session: refreshing session state\n");
267+
Environment* env = Environment::GetCurrent(args);
272268
CHECK_EQ(args.Length(), 1);
273269
CHECK(args[0]->IsObject());
274-
double* buffer = http2_session_state_buffer;
270+
double* buffer = env->http2_state_buffer()->session_state_buffer;
275271
Http2Session* session;
276272
ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>());
277273
nghttp2_session* s = session->session();
@@ -308,7 +304,7 @@ void RefreshStreamState(const FunctionCallbackInfo<Value>& args) {
308304
nghttp2_session* s = session->session();
309305
Nghttp2Stream* stream;
310306

311-
double* buffer = http2_stream_state_buffer;
307+
double* buffer = env->http2_state_buffer()->stream_state_buffer;
312308

313309
if ((stream = session->FindStream(id)) == nullptr) {
314310
buffer[IDX_STREAM_STATE] = NGHTTP2_STREAM_STATE_IDLE;
@@ -418,8 +414,9 @@ void Http2Session::SubmitPriority(const FunctionCallbackInfo<Value>& args) {
418414
void Http2Session::SubmitSettings(const FunctionCallbackInfo<Value>& args) {
419415
Http2Session* session;
420416
ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
417+
Environment* env = session->env();
421418

422-
uint32_t* buffer = http2_settings_buffer;
419+
uint32_t* buffer = env->http2_state_buffer()->settings_buffer;
423420
uint32_t flags = buffer[IDX_SETTINGS_COUNT];
424421

425422
std::vector<nghttp2_settings_entry> entries;
@@ -1148,43 +1145,27 @@ void Initialize(Local<Object> target,
11481145
Isolate* isolate = env->isolate();
11491146
HandleScope scope(isolate);
11501147

1151-
// Initialize the buffer used for padding callbacks
1152-
target->Set(context,
1153-
FIXED_ONE_BYTE_STRING(isolate, "paddingArrayBuffer"),
1154-
ArrayBuffer::New(isolate,
1155-
&http2_padding_buffer,
1156-
http2_padding_buffer_byte_length))
1157-
.FromJust();
1148+
http2_state* state = Calloc<http2_state>(1);
1149+
env->set_http2_state_buffer(state);
1150+
auto state_ab = ArrayBuffer::New(isolate, state, sizeof(*state));
11581151

1159-
// Initialize the buffer used to store the session state
1160-
target->Set(context,
1161-
FIXED_ONE_BYTE_STRING(isolate, "sessionStateArrayBuffer"),
1162-
ArrayBuffer::New(isolate,
1163-
&http2_session_state_buffer,
1164-
http2_session_state_buffer_byte_length))
1165-
.FromJust();
1152+
#define SET_STATE_TYPEDARRAY(name, type, field) \
1153+
target->Set(context, \
1154+
FIXED_ONE_BYTE_STRING(isolate, (name)), \
1155+
type::New(state_ab, \
1156+
offsetof(http2_state, field), \
1157+
arraysize(state->field))) \
1158+
.FromJust()
11661159

1160+
// Initialize the buffer used for padding callbacks
1161+
SET_STATE_TYPEDARRAY("paddingBuffer", Uint32Array, padding_buffer);
1162+
// Initialize the buffer used to store the session state
1163+
SET_STATE_TYPEDARRAY("sessionState", Float64Array, session_state_buffer);
11671164
// Initialize the buffer used to store the stream state
1168-
target->Set(context,
1169-
FIXED_ONE_BYTE_STRING(isolate, "streamStateArrayBuffer"),
1170-
ArrayBuffer::New(isolate,
1171-
&http2_stream_state_buffer,
1172-
http2_stream_state_buffer_byte_length))
1173-
.FromJust();
1174-
1175-
target->Set(context,
1176-
FIXED_ONE_BYTE_STRING(isolate, "settingsArrayBuffer"),
1177-
ArrayBuffer::New(isolate,
1178-
&http2_settings_buffer,
1179-
http2_settings_buffer_byte_length))
1180-
.FromJust();
1181-
1182-
target->Set(context,
1183-
FIXED_ONE_BYTE_STRING(isolate, "optionsArrayBuffer"),
1184-
ArrayBuffer::New(isolate,
1185-
&http2_options_buffer,
1186-
http2_options_buffer_byte_length))
1187-
.FromJust();
1165+
SET_STATE_TYPEDARRAY("streamState", Float64Array, stream_state_buffer);
1166+
SET_STATE_TYPEDARRAY("settingsBuffer", Uint32Array, settings_buffer);
1167+
SET_STATE_TYPEDARRAY("optionsBuffer", Uint32Array, options_buffer);
1168+
#undef SET_STATE_TYPEDARRAY
11881169

11891170
// Method to fetch the nghttp2 string description of an nghttp2 error code
11901171
env->SetMethod(target, "nghttp2ErrorString", HttpErrorString);

0 commit comments

Comments
 (0)