Permalink
Browse files

node: use a single, per-tick HandleScope

Avoids the creation and concomitant destruction of lots of tiny HandleScopes.

This change may increase peak memory usage with some workloads. The real
memory usage doesn't change but the garbage collector runs less often.

Speeds up the http_simple benchmark by about 2.5% in release builds and
over 11% in debug builds.
  • Loading branch information...
bnoordhuis committed Jul 5, 2012
1 parent fccb92b commit 23cf4b267badf22be96045c324b60c7dadaeedc5
Showing with 45 additions and 127 deletions.
  1. +0 −7 src/handle_wrap.cc
  2. +12 −4 src/node.cc
  3. +3 −19 src/node_http_parser.cc
  4. +10 −29 src/stream_wrap.cc
  5. +12 −43 src/tcp_wrap.cc
  6. +8 −25 src/udp_wrap.cc
View
@@ -51,8 +51,6 @@ void HandleWrap::Initialize(Handle<Object> target) {
Handle<Value> HandleWrap::Ref(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(HandleWrap)
uv_ref(wrap->handle__);
@@ -63,8 +61,6 @@ Handle<Value> HandleWrap::Ref(const Arguments& args) {
Handle<Value> HandleWrap::Unref(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(HandleWrap)
uv_unref(wrap->handle__);
@@ -75,8 +71,6 @@ Handle<Value> HandleWrap::Unref(const Arguments& args) {
Handle<Value> HandleWrap::Close(const Arguments& args) {
- HandleScope scope;
-
HandleWrap *wrap = static_cast<HandleWrap*>(
args.Holder()->GetPointerFromInternalField(0));
@@ -98,7 +92,6 @@ HandleWrap::HandleWrap(Handle<Object> object, uv_handle_t* h) {
h->data = this;
}
- HandleScope scope;
assert(object_.IsEmpty());
assert(object->InternalFieldCount() > 0);
object_ = v8::Persistent<v8::Object>::New(object);
View
@@ -2898,16 +2898,24 @@ int Start(int argc, char *argv[]) {
Handle<Object> process_l = SetupProcessObject(argc, argv);
v8_typed_array::AttachBindings(context->Global());
- // Create all the objects, load modules, do everything.
- // so your next reading stop should be node::Load()!
- Load(process_l);
+ {
+ HandleScope temp_scope;
+ // Create all the objects, load modules, do everything.
+ // so your next reading stop should be node::Load()!
+ Load(process_l);
+ }
// All our arguments are loaded. We've evaluated all of the scripts. We
// might even have created TCP servers. Now we enter the main eventloop. If
// there are no watchers on the loop (except for the ones that were
// uv_unref'd) then this function exits. As long as there are active
// watchers, it blocks.
- uv_run(uv_default_loop());
+ uv_loop_t* loop = uv_default_loop();
+
+ while (true) {
+ HandleScope temp_scope;
+ if (!uv_run_once(loop)) break;
+ }
EmitExit(process_l);
RunAtExit();
View
@@ -296,8 +296,6 @@ class Parser : public ObjectWrap {
HTTP_DATA_CB(on_body) {
- HandleScope scope;
-
Local<Value> cb = handle_->Get(on_body_sym);
if (!cb->IsFunction())
return 0;
@@ -320,8 +318,6 @@ class Parser : public ObjectWrap {
HTTP_CB(on_message_complete) {
- HandleScope scope;
-
if (num_fields_)
Flush(); // Flush trailing HTTP headers.
@@ -342,8 +338,6 @@ class Parser : public ObjectWrap {
static Handle<Value> New(const Arguments& args) {
- HandleScope scope;
-
http_parser_type type =
static_cast<http_parser_type>(args[0]->Int32Value());
@@ -374,8 +368,6 @@ class Parser : public ObjectWrap {
// var bytesParsed = parser->execute(buffer, off, len);
static Handle<Value> Execute(const Arguments& args) {
- HandleScope scope;
-
Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
assert(!current_buffer);
@@ -438,16 +430,14 @@ class Parser : public ObjectWrap {
Local<Object> obj = e->ToObject();
obj->Set(String::NewSymbol("bytesParsed"), nparsed_obj);
obj->Set(String::NewSymbol("code"), String::New(http_errno_name(err)));
- return scope.Close(e);
+ return e;
} else {
- return scope.Close(nparsed_obj);
+ return nparsed_obj;
}
}
static Handle<Value> Finish(const Arguments& args) {
- HandleScope scope;
-
Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
assert(!current_buffer);
@@ -464,16 +454,14 @@ class Parser : public ObjectWrap {
Local<Object> obj = e->ToObject();
obj->Set(String::NewSymbol("bytesParsed"), Integer::New(0));
obj->Set(String::NewSymbol("code"), String::New(http_errno_name(err)));
- return scope.Close(e);
+ return e;
}
return Undefined();
}
static Handle<Value> Reinitialize(const Arguments& args) {
- HandleScope scope;
-
http_parser_type type =
static_cast<http_parser_type>(args[0]->Int32Value());
@@ -507,8 +495,6 @@ class Parser : public ObjectWrap {
// spill headers and request path to JS land
void Flush() {
- HandleScope scope;
-
Local<Value> cb = handle_->Get(on_headers_sym);
if (!cb->IsFunction())
@@ -551,8 +537,6 @@ class Parser : public ObjectWrap {
void InitHttpParser(Handle<Object> target) {
- HandleScope scope;
-
Local<FunctionTemplate> t = FunctionTemplate::New(Parser::New);
t->InstanceTemplate()->SetInternalFieldCount(1);
t->SetClassName(String::NewSymbol("HTTPParser"));
View
@@ -41,7 +41,6 @@ using v8::Handle;
using v8::Local;
using v8::Persistent;
using v8::Value;
-using v8::HandleScope;
using v8::FunctionTemplate;
using v8::String;
using v8::Function;
@@ -93,8 +92,6 @@ void StreamWrap::Initialize(Handle<Object> target) {
slab_allocator = new SlabAllocator(SLAB_SIZE);
AtExit(DeleteSlabAllocator, NULL);
- HandleScope scope;
-
HandleWrap::Initialize(target);
buffer_sym = NODE_PSYMBOL("buffer");
@@ -122,14 +119,11 @@ void StreamWrap::SetHandle(uv_handle_t* h) {
void StreamWrap::UpdateWriteQueueSize() {
- HandleScope scope;
object_->Set(write_queue_size_sym, Integer::New(stream_->write_queue_size));
}
Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
bool ipc_pipe = wrap->stream_->type == UV_NAMED_PIPE &&
@@ -144,21 +138,19 @@ Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
Handle<Value> StreamWrap::ReadStop(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
int r = uv_read_stop(wrap->stream_);
// Error starting the tcp.
if (r) SetErrno(uv_last_error(uv_default_loop()));
- return scope.Close(Integer::New(r));
+ return Integer::New(r);
}
@@ -172,8 +164,6 @@ uv_buf_t StreamWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) {
void StreamWrap::OnReadCommon(uv_stream_t* handle, ssize_t nread,
uv_buf_t buf, uv_handle_type pending) {
- HandleScope scope;
-
StreamWrap* wrap = static_cast<StreamWrap*>(handle->data);
// We should not be getting this callback if someone as already called
@@ -242,8 +232,6 @@ void StreamWrap::OnRead2(uv_pipe_t* handle, ssize_t nread, uv_buf_t buf,
Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
// The first argument is a buffer.
@@ -256,7 +244,7 @@ Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
uv_err_t err;
err.code = UV_ENOBUFS;
SetErrno(err);
- return scope.Close(v8::Null());
+ return v8::Null();
}
char* storage = new char[sizeof(WriteWrap)];
@@ -283,16 +271,15 @@ Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
SetErrno(uv_last_error(uv_default_loop()));
req_wrap->~WriteWrap();
delete[] storage;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
template <WriteEncoding encoding>
Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
- HandleScope scope;
int r;
UNWRAP(StreamWrap)
@@ -340,7 +327,7 @@ Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
uv_err_t err;
err.code = UV_ENOBUFS;
SetErrno(err);
- return scope.Close(v8::Null());
+ return v8::Null();
}
char* storage = new char[sizeof(WriteWrap) + storage_size + 15];
@@ -416,9 +403,9 @@ Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
SetErrno(uv_last_error(uv_default_loop()));
req_wrap->~WriteWrap();
delete[] storage;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
@@ -442,8 +429,6 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) {
WriteWrap* req_wrap = (WriteWrap*) req->data;
StreamWrap* wrap = (StreamWrap*) req->handle->data;
- HandleScope scope;
-
// The wrap and request objects should still be there.
assert(req_wrap->object_.IsEmpty() == false);
assert(wrap->object_.IsEmpty() == false);
@@ -468,8 +453,6 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) {
Handle<Value> StreamWrap::Shutdown(const Arguments& args) {
- HandleScope scope;
-
UNWRAP(StreamWrap)
ShutdownWrap* req_wrap = new ShutdownWrap();
@@ -481,9 +464,9 @@ Handle<Value> StreamWrap::Shutdown(const Arguments& args) {
if (r) {
SetErrno(uv_last_error(uv_default_loop()));
delete req_wrap;
- return scope.Close(v8::Null());
+ return v8::Null();
} else {
- return scope.Close(req_wrap->object_);
+ return req_wrap->object_;
}
}
@@ -496,8 +479,6 @@ void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
assert(req_wrap->object_.IsEmpty() == false);
assert(wrap->object_.IsEmpty() == false);
- HandleScope scope;
-
if (status) {
SetErrno(uv_last_error(uv_default_loop()));
}
Oops, something went wrong.

2 comments on commit 23cf4b2

ry replied Jul 20, 2012

@mranney, @dshaw, @dannycoates: can you guys test this after you've been running on v0.8 for a while?

ry replied Jul 20, 2012

@mranney, @dshaw, @dannycoates: can you guys test this after you've been running on v0.8 for a while?

Please sign in to comment.