summaryrefslogtreecommitdiff
path: root/core/examples/http_bench.rs
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/examples/http_bench.rs
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/examples/http_bench.rs')
-rw-r--r--core/examples/http_bench.rs11
1 files changed, 8 insertions, 3 deletions
diff --git a/core/examples/http_bench.rs b/core/examples/http_bench.rs
index 3e02cdd46..b355f5568 100644
--- a/core/examples/http_bench.rs
+++ b/core/examples/http_bench.rs
@@ -111,7 +111,10 @@ fn test_record_from() {
pub type HttpBenchOp = dyn Future<Item = i32, Error = std::io::Error> + Send;
-fn dispatch(control: &[u8], zero_copy_buf: deno_buf) -> (bool, Box<Op>) {
+fn dispatch(
+ control: &[u8],
+ zero_copy_buf: Option<PinnedBuf>,
+) -> (bool, Box<Op>) {
let record = Record::from(control);
let is_sync = record.promise_id == 0;
let http_bench_op = match record.op_id {
@@ -266,8 +269,9 @@ fn op_close(rid: i32) -> Box<HttpBenchOp> {
}))
}
-fn op_read(rid: i32, mut zero_copy_buf: deno_buf) -> Box<HttpBenchOp> {
+fn op_read(rid: i32, zero_copy_buf: Option<PinnedBuf>) -> Box<HttpBenchOp> {
debug!("read rid={}", rid);
+ let mut zero_copy_buf = zero_copy_buf.unwrap();
Box::new(
futures::future::poll_fn(move || {
let mut table = RESOURCE_TABLE.lock().unwrap();
@@ -285,8 +289,9 @@ fn op_read(rid: i32, mut zero_copy_buf: deno_buf) -> Box<HttpBenchOp> {
)
}
-fn op_write(rid: i32, zero_copy_buf: deno_buf) -> Box<HttpBenchOp> {
+fn op_write(rid: i32, zero_copy_buf: Option<PinnedBuf>) -> Box<HttpBenchOp> {
debug!("write rid={}", rid);
+ let zero_copy_buf = zero_copy_buf.unwrap();
Box::new(
futures::future::poll_fn(move || {
let mut table = RESOURCE_TABLE.lock().unwrap();