summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTrevor Norris <trev.norris@gmail.com>2013-06-19 11:20:45 -0700
committerTrevor Norris <trev.norris@gmail.com>2013-07-03 14:56:27 -0700
commitec90e6e80adbb9c6f31158c319eba4e35edda845 (patch)
treeb6fe6d19a44b22677b421c6f32f4fbc11ad2e8e5 /src
parentc1db1ecd15fd796b68311c67288b395e7784defd (diff)
downloadnode-ec90e6e80adbb9c6f31158c319eba4e35edda845.tar.gz
slab_allocator: remove SlabAllocator
Now that Buffer instantiation has improved, the SlabAllocator is an unnecessary layer of complexity preventing further performance optimizations. Currently there is a small performance loss with very small stream requests, but this will soon be addressed.
Diffstat (limited to 'src')
-rw-r--r--src/slab_allocator.cc127
-rw-r--r--src/slab_allocator.h49
-rw-r--r--src/stream_wrap.cc37
-rw-r--r--src/stream_wrap.h3
-rw-r--r--src/udp_wrap.cc39
5 files changed, 30 insertions, 225 deletions
diff --git a/src/slab_allocator.cc b/src/slab_allocator.cc
deleted file mode 100644
index 1a98c8ecd..000000000
--- a/src/slab_allocator.cc
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-#include "v8.h"
-#include "node.h"
-#include "node_buffer.h"
-#include "slab_allocator.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-
-
-using v8::Handle;
-using v8::HandleScope;
-using v8::Integer;
-using v8::Local;
-using v8::Null;
-using v8::Object;
-using v8::Persistent;
-using v8::String;
-using v8::V8;
-using v8::Value;
-
-
-namespace node {
-
-SlabAllocator::SlabAllocator(unsigned int size) {
- size_ = ROUND_UP(size ? size : 1, 8192);
- initialized_ = false;
-}
-
-
-SlabAllocator::~SlabAllocator() {
- if (!initialized_) return;
- if (V8::IsDead()) return;
- slab_sym_.Dispose(node_isolate);
- slab_sym_.Clear();
- slab_.Dispose(node_isolate);
- slab_.Clear();
-}
-
-
-void SlabAllocator::Initialize() {
- HandleScope scope(node_isolate);
- char sym[256];
- snprintf(sym, sizeof(sym), "slab_%p", this); // namespace object key
- offset_ = 0;
- last_ptr_ = NULL;
- initialized_ = true;
- slab_sym_ = Persistent<String>::New(node_isolate, String::New(sym));
-}
-
-
-static Local<Object> NewSlab(unsigned int size) {
- HandleScope scope(node_isolate);
- Local<Object> buf = Buffer::New(ROUND_UP(size, 16));
- return scope.Close(buf);
-}
-
-
-char* SlabAllocator::Allocate(Handle<Object> obj, unsigned int size) {
- HandleScope scope(node_isolate);
-
- assert(!obj.IsEmpty());
-
- if (size == 0) return NULL;
- if (!initialized_) Initialize();
-
- if (size > size_) {
- Local<Object> buf = NewSlab(size);
- obj->SetHiddenValue(slab_sym_, buf);
- return Buffer::Data(buf);
- }
-
- if (slab_.IsEmpty() || offset_ + size > size_) {
- slab_.Dispose(node_isolate);
- slab_.Clear();
- slab_ = Persistent<Object>::New(node_isolate, NewSlab(size_));
- offset_ = 0;
- last_ptr_ = NULL;
- }
-
- obj->SetHiddenValue(slab_sym_, slab_);
- last_ptr_ = Buffer::Data(slab_) + offset_;
- offset_ += size;
-
- return last_ptr_;
-}
-
-
-Local<Object> SlabAllocator::Shrink(Handle<Object> obj,
- char* ptr,
- unsigned int size) {
- HandleScope scope(node_isolate);
- Local<Value> slab_v = obj->GetHiddenValue(slab_sym_);
- obj->SetHiddenValue(slab_sym_, Null(node_isolate));
- assert(!slab_v.IsEmpty());
- assert(slab_v->IsObject());
- Local<Object> slab = slab_v->ToObject();
- assert(ptr != NULL);
- if (ptr == last_ptr_) {
- last_ptr_ = NULL;
- offset_ = ptr - Buffer::Data(slab) + ROUND_UP(size, 16);
- }
- return scope.Close(slab);
-}
-
-
-} // namespace node
diff --git a/src/slab_allocator.h b/src/slab_allocator.h
deleted file mode 100644
index 6440bd4a0..000000000
--- a/src/slab_allocator.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-#include "v8.h"
-
-namespace node {
-
-class SlabAllocator {
-public:
- SlabAllocator(unsigned int size = 10485760); // default to 10M
- ~SlabAllocator();
-
- // allocate memory from slab, attaches the slice to `obj`
- char* Allocate(v8::Handle<v8::Object> obj, unsigned int size);
-
- // return excess memory to the slab, returns a handle to the parent buffer
- v8::Local<v8::Object> Shrink(v8::Handle<v8::Object> obj,
- char* ptr,
- unsigned int size);
-
-private:
- void Initialize();
- bool initialized_;
- v8::Persistent<v8::Object> slab_;
- v8::Persistent<v8::String> slab_sym_;
- unsigned int offset_;
- unsigned int size_;
- char* last_ptr_;
-};
-
-} // namespace node
diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc
index 886cf648e..9b33d62b5 100644
--- a/src/stream_wrap.cc
+++ b/src/stream_wrap.cc
@@ -22,7 +22,6 @@
#include "node.h"
#include "node_buffer.h"
#include "handle_wrap.h"
-#include "slab_allocator.h"
#include "stream_wrap.h"
#include "pipe_wrap.h"
#include "tcp_wrap.h"
@@ -33,8 +32,6 @@
#include <stdlib.h> // abort()
#include <limits.h> // INT_MAX
-#define SLAB_SIZE (1024 * 1024)
-
namespace node {
@@ -49,6 +46,7 @@ using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
+using v8::Uint32;
using v8::Value;
@@ -58,23 +56,13 @@ static Persistent<String> write_queue_size_sym;
static Persistent<String> onread_sym;
static Persistent<String> oncomplete_sym;
static Persistent<String> handle_sym;
-static SlabAllocator* slab_allocator;
static bool initialized;
-static void DeleteSlabAllocator(void*) {
- delete slab_allocator;
- slab_allocator = NULL;
-}
-
-
void StreamWrap::Initialize(Handle<Object> target) {
if (initialized) return;
initialized = true;
- slab_allocator = new SlabAllocator(SLAB_SIZE);
- AtExit(DeleteSlabAllocator, NULL);
-
HandleScope scope(node_isolate);
HandleWrap::Initialize(target);
@@ -592,8 +580,7 @@ void StreamWrapCallbacks::AfterWrite(WriteWrap* w) {
uv_buf_t StreamWrapCallbacks::DoAlloc(uv_handle_t* handle,
size_t suggested_size) {
- char* buf = slab_allocator->Allocate(wrap_->object_, suggested_size);
- return uv_buf_init(buf, suggested_size);
+ return uv_buf_init(new char[suggested_size], suggested_size);
}
@@ -604,26 +591,30 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
HandleScope scope(node_isolate);
if (nread < 0) {
- // If libuv reports an error or EOF it *may* give us a buffer back. In that
- // case, return the space to the slab.
if (buf.base != NULL)
- slab_allocator->Shrink(Self(), buf.base, 0);
+ delete[] buf.base;
SetErrno(uv_last_error(uv_default_loop()));
MakeCallback(Self(), onread_sym, 0, NULL);
return;
}
- Local<Object> slab = slab_allocator->Shrink(wrap_->object_, buf.base, nread);
+ if (nread == 0) {
+ if (buf.base != NULL)
+ delete[] buf.base;
+ return;
+ }
+
+ // TODO(trevnorris): not kosher to use new/delete w/ realloc
+ buf.base = static_cast<char*>(realloc(buf.base, nread));
- if (nread == 0) return;
assert(static_cast<size_t>(nread) <= buf.len);
int argc = 3;
Local<Value> argv[4] = {
- slab,
- Integer::NewFromUnsigned(buf.base - Buffer::Data(slab), node_isolate),
- Integer::NewFromUnsigned(nread, node_isolate)
+ Buffer::Use(buf.base, nread),
+ Uint32::New(0, node_isolate),
+ Uint32::New(nread, node_isolate)
};
Local<Object> pending_obj;
diff --git a/src/stream_wrap.h b/src/stream_wrap.h
index 6b73efd68..5ac725b4c 100644
--- a/src/stream_wrap.h
+++ b/src/stream_wrap.h
@@ -135,8 +135,6 @@ class StreamWrap : public HandleWrap {
void UpdateWriteQueueSize();
private:
- static inline char* NewSlab(v8::Handle<v8::Object> global, v8::Handle<v8::Object> wrap_obj);
-
// Callbacks for libuv
static void AfterWrite(uv_write_t* req, int status);
static uv_buf_t OnAlloc(uv_handle_t* handle, size_t suggested_size);
@@ -151,7 +149,6 @@ class StreamWrap : public HandleWrap {
template <enum encoding encoding>
static v8::Handle<v8::Value> WriteStringImpl(const v8::Arguments& args);
- size_t slab_offset_;
uv_stream_t* stream_;
StreamWrapCallbacks default_callbacks_;
diff --git a/src/udp_wrap.cc b/src/udp_wrap.cc
index b463a75c8..db759e6ed 100644
--- a/src/udp_wrap.cc
+++ b/src/udp_wrap.cc
@@ -21,15 +21,12 @@
#include "node.h"
#include "node_buffer.h"
-#include "slab_allocator.h"
#include "req_wrap.h"
#include "handle_wrap.h"
#include "udp_wrap.h"
#include <stdlib.h>
-#define SLAB_SIZE (1024 * 1024)
-
namespace node {
@@ -45,6 +42,7 @@ using v8::Object;
using v8::Persistent;
using v8::PropertyAttribute;
using v8::String;
+using v8::Uint32;
using v8::Value;
typedef ReqWrap<uv_udp_send_t> SendWrap;
@@ -56,13 +54,6 @@ static Persistent<Function> constructor;
static Persistent<String> buffer_sym;
static Persistent<String> oncomplete_sym;
static Persistent<String> onmessage_sym;
-static SlabAllocator* slab_allocator;
-
-
-static void DeleteSlabAllocator(void*) {
- delete slab_allocator;
- slab_allocator = NULL;
-}
UDPWrap::UDPWrap(Handle<Object> object)
@@ -79,9 +70,6 @@ UDPWrap::~UDPWrap() {
void UDPWrap::Initialize(Handle<Object> target) {
HandleWrap::Initialize(target);
- slab_allocator = new SlabAllocator(SLAB_SIZE);
- AtExit(DeleteSlabAllocator, NULL);
-
HandleScope scope(node_isolate);
buffer_sym = NODE_PSYMBOL("buffer");
@@ -383,9 +371,7 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
uv_buf_t UDPWrap::OnAlloc(uv_handle_t* handle, size_t suggested_size) {
- UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
- char* buf = slab_allocator->Allocate(wrap->object_, suggested_size);
- return uv_buf_init(buf, suggested_size);
+ return uv_buf_init(new char[suggested_size], suggested_size);
}
@@ -397,23 +383,30 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
HandleScope scope(node_isolate);
UDPWrap* wrap = reinterpret_cast<UDPWrap*>(handle->data);
- Local<Object> slab = slab_allocator->Shrink(wrap->object_,
- buf.base,
- nread < 0 ? 0 : nread);
- if (nread == 0) return;
if (nread < 0) {
+ if (buf.base != NULL)
+ delete[] buf.base;
Local<Value> argv[] = { Local<Object>::New(node_isolate, wrap->object_) };
SetErrno(uv_last_error(uv_default_loop()));
MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);
return;
}
+ if (nread == 0) {
+ if (buf.base != NULL)
+ delete[] buf.base;
+ return;
+ }
+
+ // TODO(trevnorris): not kosher to use new/delete w/ realloc
+ buf.base = static_cast<char*>(realloc(buf.base, nread));
+
Local<Value> argv[] = {
Local<Object>::New(node_isolate, wrap->object_),
- slab,
- Integer::NewFromUnsigned(buf.base - Buffer::Data(slab), node_isolate),
- Integer::NewFromUnsigned(nread, node_isolate),
+ Buffer::Use(buf.base, nread),
+ Uint32::New(0, node_isolate),
+ Uint32::New(nread, node_isolate),
AddressToJS(addr)
};
MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);