summaryrefslogtreecommitdiff
path: root/core/libdeno/deno.h
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2019-04-28 21:31:10 +0200
committerBert Belder <bertbelder@gmail.com>2019-05-01 21:11:09 +0200
commit41c7e96f1a81ea416ebb3ba45f2815e0202d6b75 (patch)
tree5fcb15b8664d7579cf4db76d16754c8efa7c4667 /core/libdeno/deno.h
parentabdb98a2516a9d6ec313805dffbc2107d38f8ed4 (diff)
Refactor zero-copy buffers for performance and to prevent memory leaks
* In order to prevent ArrayBuffers from getting garbage collected by V8, we used to store a v8::Persistent<ArrayBuffer> in a map. This patch introduces a custom ArrayBuffer allocator which doesn't use Persistent handles, but instead stores a pointer to the actual ArrayBuffer data alongside with a reference count. Since creating Persistent handles has quite a bit of overhead, this change significantly increases performance. Various HTTP server benchmarks report about 5-10% more requests per second than before. * Previously the Persistent handle that prevented garbage collection had to be released manually, and this wasn't always done, which was causing memory leaks. This has been resolved by introducing a new `PinnedBuf` type in both Rust and C++ that automatically re-enables garbage collection when it goes out of scope. * Zero-copy buffers are now correctly wrapped in an Option if there is a possibility that they're not present. This clears up a correctness issue where we were creating zero-length slices from a null pointer, which is against the rules.
Diffstat (limited to 'core/libdeno/deno.h')
-rw-r--r--core/libdeno/deno.h15
1 files changed, 9 insertions, 6 deletions
diff --git a/core/libdeno/deno.h b/core/libdeno/deno.h
index 8054090ed..f83f00834 100644
--- a/core/libdeno/deno.h
+++ b/core/libdeno/deno.h
@@ -1,21 +1,26 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
#ifndef DENO_H_
#define DENO_H_
+
#include <stddef.h>
#include <stdint.h>
+
+#include "buffer.h"
+
// Neither Rust nor Go support calling directly into C++ functions, therefore
// the public interface to libdeno is done in C.
#ifdef __cplusplus
extern "C" {
#endif
+typedef deno::PinnedBuf::Raw deno_pinned_buf;
+
// Data that gets transmitted.
typedef struct {
- uint8_t* alloc_ptr; // Start of memory allocation (returned from `malloc()`).
+ uint8_t* alloc_ptr; // Start of memory allocation (from `new uint8_t[len]`).
size_t alloc_len; // Length of the memory allocation.
uint8_t* data_ptr; // Start of logical contents (within the allocation).
size_t data_len; // Length of logical contents.
- size_t zero_copy_id; // 0 = normal, 1 = must call deno_zero_copy_release.
} deno_buf;
typedef struct {
@@ -29,7 +34,7 @@ typedef struct deno_s Deno;
// control_buf is valid for only for the lifetime of this callback.
// data_buf is valid until deno_respond() is called.
typedef void (*deno_recv_cb)(void* user_data, deno_buf control_buf,
- deno_buf zerop_copy_buf);
+ deno_pinned_buf zero_copy_buf);
void deno_init();
const char* deno_v8_version();
@@ -84,9 +89,7 @@ void deno_execute(Deno* d, void* user_data, const char* js_filename,
void deno_respond(Deno* d, void* user_data, deno_buf buf);
// consumes zero_copy
-// Calling this function more than once with the same zero_copy_id will result
-// in an error.
-void deno_zero_copy_release(Deno* d, size_t zero_copy_id);
+void deno_pinned_buf_delete(deno_pinned_buf* buf);
void deno_check_promise_errors(Deno* d);