GeezerVison is showing github.com — stream: reuse unexposed managed read buffers · nodejs/node@e2b522b
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: src/env.cc +17-4Lines changed: 17 additions & 4 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -76,6 +76,8 @@ using v8::Undefined; | 76 | 76 | using v8::Value; | 77 | 77 | using worker::Worker; | 78 | 78 |
| | 79 | +constexpr size_t kManagedBufferCacheSize = 64 * 1024; | | 80 | + | 79 | 81 | int const ContextEmbedderTag::kNodeContextTag = 0x6e6f64; | 80 | 82 | void* const ContextEmbedderTag::kNodeContextTagPtr = const_cast<void*>( | 81 | 83 | static_cast<const void*>(&ContextEmbedderTag::kNodeContextTag)); | @@ -766,10 +768,16 @@ void Environment::add_refs(int64_t diff) { | 766 | 768 | } | 767 | 769 |
| 768 | 770 | uv_buf_t Environment::allocate_managed_buffer(const size_t suggested_size) { | 769 | | - std::unique_ptr<BackingStore> bs = ArrayBuffer::NewBackingStore( | 770 | | - isolate(), | 771 | | - suggested_size, | 772 | | - BackingStoreInitializationMode::kUninitialized); | | 771 | + std::unique_ptr<BackingStore> bs; | | 772 | + if (suggested_size == kManagedBufferCacheSize && | | 773 | + managed_buffer_cache_ != nullptr) { | | 774 | + bs = std::move(managed_buffer_cache_); | | 775 | + } else { | | 776 | + bs = ArrayBuffer::NewBackingStore( | | 777 | + isolate(), | | 778 | + suggested_size, | | 779 | + BackingStoreInitializationMode::kUninitialized); | | 780 | + } | 773 | 781 | uv_buf_t buf = uv_buf_init(static_cast<char*>(bs->Data()), bs->ByteLength()); | 774 | 782 | released_allocated_buffers_.emplace(buf.base, std::move(bs)); | 775 | 783 | return buf; | @@ -787,6 +795,11 @@ std::unique_ptr<BackingStore> Environment::release_managed_buffer( | 787 | 795 | return bs; | 788 | 796 | } | 789 | 797 |
| | 798 | +void Environment::recycle_managed_buffer(std::unique_ptr<BackingStore> bs) { | | 799 | + if (bs != nullptr && bs->ByteLength() == kManagedBufferCacheSize) | | 800 | + managed_buffer_cache_ = std::move(bs); | | 801 | +} | | 802 | + | 790 | 803 | std::string Environment::GetExecPath(const std::vector<std::string>& argv) { | 791 | 804 | char exec_path_buf[2 * PATH_MAX]; | 792 | 805 | size_t exec_path_len = sizeof(exec_path_buf); | |
Collapse file Copy file name to clipboardExpand all lines: src/env.h +3Lines changed: 3 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -1057,6 +1057,8 @@ class Environment final : public MemoryRetainer { | 1057 | 1057 |
| 1058 | 1058 | uv_buf_t allocate_managed_buffer(const size_t suggested_size); | 1059 | 1059 | std::unique_ptr<v8::BackingStore> release_managed_buffer(const uv_buf_t& buf); | | 1060 | + // Only buffers that were not exposed externally may be recycled. | | 1061 | + void recycle_managed_buffer(std::unique_ptr<v8::BackingStore> bs); | 1060 | 1062 |
| 1061 | 1063 | void AddUnmanagedFd(int fd); | 1062 | 1064 | void RemoveUnmanagedFd(int fd); | @@ -1274,6 +1276,7 @@ class Environment final : public MemoryRetainer { | 1274 | 1276 | // track of the BackingStore for a given pointer. | 1275 | 1277 | std::unordered_map<char*, std::unique_ptr<v8::BackingStore>> | 1276 | 1278 | released_allocated_buffers_; | | 1279 | + std::unique_ptr<v8::BackingStore> managed_buffer_cache_; | 1277 | 1280 |
| 1278 | 1281 | v8::CpuProfiler* cpu_profiler_ = nullptr; | 1279 | 1282 | std::vector<v8::ProfilerId> pending_profiles_; | |
Collapse file Copy file name to clipboardExpand all lines: src/stream_base.cc +2Lines changed: 2 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -696,6 +696,7 @@ void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { | 696 | 696 | std::unique_ptr<BackingStore> bs = env->release_managed_buffer(buf_); | 697 | 697 |
| 698 | 698 | if (nread <= 0) { | | 699 | + env->recycle_managed_buffer(std::move(bs)); | 699 | 700 | if (nread < 0) | 700 | 701 | stream->CallJSOnreadMethod(nread, Local<ArrayBuffer>()); | 701 | 702 | return; | @@ -707,6 +708,7 @@ void EmitToJSStreamListener::OnStreamRead(ssize_t nread, const uv_buf_t& buf_) { | 707 | 708 | bs = ArrayBuffer::NewBackingStore( | 708 | 709 | isolate, nread, BackingStoreInitializationMode::kUninitialized); | 709 | 710 | memcpy(bs->Data(), old_bs->Data(), nread); | | 711 | + env->recycle_managed_buffer(std::move(old_bs)); | 710 | 712 | } | 711 | 713 |
| 712 | 714 | stream->CallJSOnreadMethod(nread, ArrayBuffer::New(isolate, std::move(bs))); | |
Collapse file Copy file name to clipboardExpand all lines: test/cctest/test_environment.cc +21Lines changed: 21 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -38,6 +38,27 @@ class EnvironmentTest : public EnvironmentTestFixture { | 38 | 38 | } | 39 | 39 | }; | 40 | 40 |
| | 41 | +TEST_F(EnvironmentTest, ManagedBufferCache) { | | 42 | + constexpr size_t kCacheSize = 64 * 1024; | | 43 | + constexpr size_t kOtherSize = 1024; | | 44 | + const v8::HandleScope handle_scope(isolate_); | | 45 | + Argv argv; | | 46 | + Env env{handle_scope, argv}; | | 47 | + | | 48 | + (*env)->recycle_managed_buffer(nullptr); | | 49 | + | | 50 | + uv_buf_t buffer = (*env)->allocate_managed_buffer(kCacheSize); | | 51 | + char* cached_data = buffer.base; | | 52 | + (*env)->recycle_managed_buffer((*env)->release_managed_buffer(buffer)); | | 53 | + | | 54 | + buffer = (*env)->allocate_managed_buffer(kOtherSize); | | 55 | + (*env)->recycle_managed_buffer((*env)->release_managed_buffer(buffer)); | | 56 | + | | 57 | + buffer = (*env)->allocate_managed_buffer(kCacheSize); | | 58 | + EXPECT_EQ(buffer.base, cached_data); | | 59 | + (*env)->release_managed_buffer(buffer); | | 60 | +} | | 61 | + | 41 | 62 | TEST_F(EnvironmentTest, EnvironmentWithoutBrowserGlobals) { | 42 | 63 | const v8::HandleScope handle_scope(isolate_); | 43 | 64 | Argv argv; | |
|