diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2012-01-17 03:20:26 +0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2012-01-17 03:20:26 +0400 |
commit | ca2a047b8e044e72e0bd8d2200de97ac995b945b (patch) | |
tree | 7d6bb421e1e14dbf1e7d68c9057cf99e50a8cd39 /src | |
parent | 7584225873cd27b53f3fdfb6af5c12c6514acdfa (diff) | |
parent | 25410096b4c38eb9b17501ea06349872ab33e1ea (diff) |
Merge remote branch 'origin/v0.6'
Conflicts:
deps/uv/src/win/util.c
src/udp_wrap.cc
Diffstat (limited to 'src')
-rw-r--r-- | src/udp_wrap.cc | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc index a6b7649e435..6d79410779a 100644 --- a/src/udp_wrap.cc +++ b/src/udp_wrap.cc @@ -60,10 +60,14 @@ namespace node { return scope.Close(Integer::New(-1)); \ } +#define SLAB_SIZE (1024 * 1024) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + // TODO share with tcp_wrap.cc Persistent<String> address_symbol; Persistent<String> port_symbol; Persistent<String> buffer_sym; +static Persistent<String> udp_slab_sym; void AddressToJS(Handle<Object> info, const sockaddr* addr, @@ -71,6 +75,12 @@ void AddressToJS(Handle<Object> info, typedef ReqWrap<uv_udp_send_t> SendWrap; + +static size_t slab_used; +size_t slab_offset_; +static uv_handle_t* handle_that_last_alloced; + + class UDPWrap: public HandleWrap { public: static void Initialize(Handle<Object> target); @@ -84,6 +94,8 @@ public: static Handle<Value> GetSockName(const Arguments& args); private: + static inline char* NewSlab(v8::Handle<v8::Object> global, v8::Handle<v8::Object> wrap_obj); + UDPWrap(Handle<Object> object); virtual ~UDPWrap(); @@ -119,6 +131,7 @@ void UDPWrap::Initialize(Handle<Object> target) { HandleScope scope; + udp_slab_sym = Persistent<String>::New(String::NewSymbol("udpslab")); buffer_sym = NODE_PSYMBOL("buffer"); port_symbol = NODE_PSYMBOL("port"); address_symbol = NODE_PSYMBOL("address"); @@ -150,7 +163,6 @@ Handle<Value> UDPWrap::New(const Arguments& args) { return scope.Close(args.This()); } - Handle<Value> UDPWrap::DoBind(const Arguments& args, int family) { HandleScope scope; int r; @@ -333,13 +345,44 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) { uv_buf_t UDPWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) { - // FIXME switch to slab allocation, share with stream_wrap.cc - return uv_buf_init(new char[suggested_size], suggested_size); -} + HandleScope scope; + + UDPWrap* wrap = static_cast<UDPWrap*>(handle->data); + + char* slab = NULL; + + Handle<Object> global = Context::GetCurrent()->Global(); + Local<Value> slab_v = global->GetHiddenValue(udp_slab_sym); + + if (slab_v.IsEmpty()) { + // No slab currently. Create a new one. + slab = NewSlab(global, wrap->object_); + } else { + // Use existing slab. + Local<Object> slab_obj = slab_v->ToObject(); + slab = Buffer::Data(slab_obj); + assert(Buffer::Length(slab_obj) == SLAB_SIZE); + assert(SLAB_SIZE >= slab_used); + + // If less than 64kb is remaining on the slab allocate a new one. + if (SLAB_SIZE - slab_used < 64 * 1024) { + slab = NewSlab(global, wrap->object_); + } else { + wrap->object_->SetHiddenValue(udp_slab_sym, slab_obj); + } + } + + uv_buf_t buf; + buf.base = slab + slab_used; + buf.len = MIN(SLAB_SIZE - slab_used, suggested_size); + slab_offset_ = slab_used; + slab_used += buf.len; + + handle_that_last_alloced = reinterpret_cast<uv_handle_t*>(handle); + + return buf; -static void ReleaseMemory(char* data, void* arg) { - delete[] data; // data == buf.base } @@ -349,7 +392,6 @@ void UDPWrap::OnRecv(uv_udp_t* handle, struct sockaddr* addr, unsigned flags) { if (nread == 0) { - ReleaseMemory(buf.base, NULL); return; } @@ -366,18 +408,26 @@ void UDPWrap::OnRecv(uv_udp_t* handle, if (nread == -1) { SetErrno(uv_last_error(Loop())); - ReleaseMemory(buf.base, NULL); } else { Local<Object> rinfo = Object::New(); AddressToJS(rinfo, addr, sizeof *addr); - argv[2] = Buffer::New(buf.base, nread, ReleaseMemory, NULL)->handle_; + argv[2] = Buffer::New(buf.base, nread, NULL, NULL)->handle_; argv[3] = rinfo; } MakeCallback(wrap->object_, "onmessage", ARRAY_SIZE(argv), argv); } +inline char* UDPWrap::NewSlab(Handle<Object> global, + Handle<Object> wrap_obj) { + Buffer* b = Buffer::New(SLAB_SIZE); + global->SetHiddenValue(udp_slab_sym, b->handle_); + assert(Buffer::Length(b) == SLAB_SIZE); + slab_used = 0; + wrap_obj->SetHiddenValue(udp_slab_sym, b->handle_); + return Buffer::Data(b); +} void AddressToJS(Handle<Object> info, const sockaddr* addr, |