Skip to content

Commit 284f033

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 b1c2264 commit 284f033

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"
@@ -505,101 +506,20 @@ Http2Session::Callbacks::~Callbacks() {
505506
nghttp2_session_callbacks_del(callbacks);
506507
}
507508

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

596-
inline nghttp2_mem* operator*() { return &info; }
513+
void Http2Session::CheckAllocatedSize(size_t previous_size) const {
514+
CHECK_GE(current_nghttp2_memory_, previous_size);
515+
}
597516

598-
nghttp2_mem info;
599-
};
517+
void Http2Session::IncreaseAllocatedSize(size_t size) {
518+
current_nghttp2_memory_ += size;
519+
}
600520

601-
void Http2Session::StopTrackingRcbuf(nghttp2_rcbuf* buf) {
602-
MemoryAllocatorInfo::StopTracking(this, buf);
521+
void Http2Session::DecreaseAllocatedSize(size_t size) {
522+
current_nghttp2_memory_ -= size;
603523
}
604524

605525
Http2Session::Http2Session(Environment* env,
@@ -636,14 +556,14 @@ Http2Session::Http2Session(Environment* env,
636556
nghttp2_session_server_new3 :
637557
nghttp2_session_client_new3;
638558

639-
MemoryAllocatorInfo allocator_info(this);
559+
nghttp2_mem alloc_info = MakeAllocator();
640560

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

648568
outgoing_storage_.reserve(1024);
649569
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"
@@ -705,7 +706,9 @@ enum SessionBitfieldFlags {
705706
kSessionHasAltsvcListeners
706707
};
707708

708-
class Http2Session : public AsyncWrap, public StreamListener {
709+
class Http2Session : public AsyncWrap,
710+
public StreamListener,
711+
public mem::NgLibMemoryManager<Http2Session, nghttp2_mem> {
709712
public:
710713
Http2Session(Environment* env,
711714
Local<Object> wrap,
@@ -714,7 +717,6 @@ class Http2Session : public AsyncWrap, public StreamListener {
714717

715718
class Http2Ping;
716719
class Http2Settings;
717-
class MemoryAllocatorInfo;
718720

719721
void EmitStatistics();
720722

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

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

0 commit comments

Comments
 (0)