Skip to content

Commit 8a9f57d

Browse files
addaleaxtargos
authored andcommitted
http2: use shared memory tracking implementation
The extensive testing done on http2 makes it easier to make sure the implementation is correct (and doesn’t diverge unnecessarily). Refs: nodejs/quic#126 Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: James M Snell <[email protected]> PR-URL: #30745 Refs: https://github.com/nodejs/quic/blob/34ee0bc96f804c73cb22b2945a1a78f780938492/src/node_mem.h Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Rich Trott <[email protected]>
1 parent 041daaa commit 8a9f57d

File tree

2 files changed

+23
-96
lines changed

2 files changed

+23
-96
lines changed

src/node_http2.cc

+14-94
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "node_buffer.h"
66
#include "node_http2.h"
77
#include "node_http2_state.h"
8+
#include "node_mem-inl.h"
89
#include "node_perf.h"
910
#include "node_revert.h"
1011
#include "util-inl.h"
@@ -501,101 +502,20 @@ Http2Session::Callbacks::~Callbacks() {
501502
nghttp2_session_callbacks_del(callbacks);
502503
}
503504

504-
// Track memory allocated by nghttp2 using a custom allocator.
505-
class Http2Session::MemoryAllocatorInfo {
506-
public:
507-
explicit MemoryAllocatorInfo(Http2Session* session)
508-
: info({ session, H2Malloc, H2Free, H2Calloc, H2Realloc }) {}
509-
510-
static void* H2Malloc(size_t size, void* user_data) {
511-
return H2Realloc(nullptr, size, user_data);
512-
}
513-
514-
static void* H2Calloc(size_t nmemb, size_t size, void* user_data) {
515-
size_t real_size = MultiplyWithOverflowCheck(nmemb, size);
516-
void* mem = H2Malloc(real_size, user_data);
517-
if (mem != nullptr)
518-
memset(mem, 0, real_size);
519-
return mem;
520-
}
521-
522-
static void H2Free(void* ptr, void* user_data) {
523-
if (ptr == nullptr) return; // free(null); happens quite often.
524-
void* result = H2Realloc(ptr, 0, user_data);
525-
CHECK_NULL(result);
526-
}
527-
528-
static void* H2Realloc(void* ptr, size_t size, void* user_data) {
529-
Http2Session* session = static_cast<Http2Session*>(user_data);
530-
size_t previous_size = 0;
531-
char* original_ptr = nullptr;
532-
533-
// We prepend each allocated buffer with a size_t containing the full
534-
// size of the allocation.
535-
if (size > 0) size += sizeof(size_t);
536-
537-
if (ptr != nullptr) {
538-
// We are free()ing or re-allocating.
539-
original_ptr = static_cast<char*>(ptr) - sizeof(size_t);
540-
previous_size = *reinterpret_cast<size_t*>(original_ptr);
541-
// This means we called StopTracking() on this pointer before.
542-
if (previous_size == 0) {
543-
// Fall back to the standard Realloc() function.
544-
char* ret = UncheckedRealloc(original_ptr, size);
545-
if (ret != nullptr)
546-
ret += sizeof(size_t);
547-
return ret;
548-
}
549-
}
550-
CHECK_GE(session->current_nghttp2_memory_, previous_size);
551-
552-
// TODO(addaleax): Add the following, and handle NGHTTP2_ERR_NOMEM properly
553-
// everywhere:
554-
//
555-
// if (size > previous_size &&
556-
// !session->IsAvailableSessionMemory(size - previous_size)) {
557-
// return nullptr;
558-
//}
559-
560-
char* mem = UncheckedRealloc(original_ptr, size);
561-
562-
if (mem != nullptr) {
563-
// Adjust the memory info counter.
564-
// TODO(addaleax): Avoid the double bookkeeping we do with
565-
// current_nghttp2_memory_ + AdjustAmountOfExternalAllocatedMemory
566-
// and provide versions of our memory allocation utilities that take an
567-
// Environment*/Isolate* parameter and call the V8 method transparently.
568-
const int64_t new_size = size - previous_size;
569-
session->current_nghttp2_memory_ += new_size;
570-
session->env()->isolate()->AdjustAmountOfExternalAllocatedMemory(
571-
new_size);
572-
*reinterpret_cast<size_t*>(mem) = size;
573-
mem += sizeof(size_t);
574-
} else if (size == 0) {
575-
session->current_nghttp2_memory_ -= previous_size;
576-
session->env()->isolate()->AdjustAmountOfExternalAllocatedMemory(
577-
-static_cast<int64_t>(previous_size));
578-
}
579-
580-
return mem;
581-
}
582-
583-
static void StopTracking(Http2Session* session, void* ptr) {
584-
size_t* original_ptr = reinterpret_cast<size_t*>(
585-
static_cast<char*>(ptr) - sizeof(size_t));
586-
session->current_nghttp2_memory_ -= *original_ptr;
587-
session->env()->isolate()->AdjustAmountOfExternalAllocatedMemory(
588-
-static_cast<int64_t>(*original_ptr));
589-
*original_ptr = 0;
590-
}
505+
void Http2Session::StopTrackingRcbuf(nghttp2_rcbuf* buf) {
506+
StopTrackingMemory(buf);
507+
}
591508

592-
inline nghttp2_mem* operator*() { return &info; }
509+
void Http2Session::CheckAllocatedSize(size_t previous_size) const {
510+
CHECK_GE(current_nghttp2_memory_, previous_size);
511+
}
593512

594-
nghttp2_mem info;
595-
};
513+
void Http2Session::IncreaseAllocatedSize(size_t size) {
514+
current_nghttp2_memory_ += size;
515+
}
596516

597-
void Http2Session::StopTrackingRcbuf(nghttp2_rcbuf* buf) {
598-
MemoryAllocatorInfo::StopTracking(this, buf);
517+
void Http2Session::DecreaseAllocatedSize(size_t size) {
518+
current_nghttp2_memory_ -= size;
599519
}
600520

601521
Http2Session::Http2Session(Environment* env,
@@ -632,14 +552,14 @@ Http2Session::Http2Session(Environment* env,
632552
nghttp2_session_server_new3 :
633553
nghttp2_session_client_new3;
634554

635-
MemoryAllocatorInfo allocator_info(this);
555+
nghttp2_mem alloc_info = MakeAllocator();
636556

637557
// This should fail only if the system is out of memory, which
638558
// is going to cause lots of other problems anyway, or if any
639559
// of the options are out of acceptable range, which we should
640560
// be catching before it gets this far. Either way, crash if this
641561
// fails.
642-
CHECK_EQ(fn(&session_, callbacks, this, *opts, *allocator_info), 0);
562+
CHECK_EQ(fn(&session_, callbacks, this, *opts, &alloc_info), 0);
643563

644564
outgoing_storage_.reserve(1024);
645565
outgoing_buffers_.reserve(32);

src/node_http2.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "nghttp2/nghttp2.h"
99

1010
#include "node_http2_state.h"
11+
#include "node_mem.h"
1112
#include "node_perf.h"
1213
#include "stream_base-inl.h"
1314
#include "string_bytes.h"
@@ -703,7 +704,9 @@ enum SessionBitfieldFlags {
703704
kSessionHasAltsvcListeners
704705
};
705706

706-
class Http2Session : public AsyncWrap, public StreamListener {
707+
class Http2Session : public AsyncWrap,
708+
public StreamListener,
709+
public mem::NgLibMemoryManager<Http2Session, nghttp2_mem> {
707710
public:
708711
Http2Session(Environment* env,
709712
Local<Object> wrap,
@@ -712,7 +715,6 @@ class Http2Session : public AsyncWrap, public StreamListener {
712715

713716
class Http2Ping;
714717
class Http2Settings;
715-
class MemoryAllocatorInfo;
716718

717719
void EmitStatistics();
718720

@@ -813,6 +815,11 @@ class Http2Session : public AsyncWrap, public StreamListener {
813815
void OnStreamRead(ssize_t nread, const uv_buf_t& buf) override;
814816
void OnStreamAfterWrite(WriteWrap* w, int status) override;
815817

818+
// Implementation for mem::NgLibMemoryManager
819+
void CheckAllocatedSize(size_t previous_size) const;
820+
void IncreaseAllocatedSize(size_t size);
821+
void DecreaseAllocatedSize(size_t size);
822+
816823
// The JavaScript API
817824
static void New(const FunctionCallbackInfo<Value>& args);
818825
static void Consume(const FunctionCallbackInfo<Value>& args);

0 commit comments

Comments
 (0)