buffer: add NativeBuffer API
Due to a lot of the util.is* checks there was much unnecessary overhead for the most common use case of Buffer. Which is creating a new Buffer instance for data from incoming I/O. NativeBuffer is a simple way to bypass all the unneeded checks and simply hand back a Buffer instance while setting the length.
This commit is contained in:
parent
9ac75d1f06
commit
16a60ed2a3
@ -31,8 +31,6 @@ exports.Buffer = Buffer;
|
||||
exports.SlowBuffer = SlowBuffer;
|
||||
exports.INSPECT_MAX_BYTES = 50;
|
||||
|
||||
// add methods to Buffer prototype
|
||||
buffer.setupBufferJS(Buffer, internal);
|
||||
|
||||
Buffer.poolSize = 8 * 1024;
|
||||
var poolSize = Buffer.poolSize;
|
||||
@ -57,13 +55,6 @@ function Buffer(subject, encoding) {
|
||||
this.length = Buffer.byteLength(subject, encoding = encoding || 'utf8');
|
||||
else if (util.isObject(subject))
|
||||
this.length = +subject.length > 0 ? Math.floor(+subject.length) : 0;
|
||||
else if (util.isUndefined(subject)) {
|
||||
// undef first arg returns unallocated buffer, also assumes length passed.
|
||||
// this is a stop-gap for now while look for better architecture.
|
||||
// for internal use only.
|
||||
this.length = encoding;
|
||||
return;
|
||||
}
|
||||
else
|
||||
throw new TypeError('must start with number, buffer, array or string');
|
||||
|
||||
@ -99,12 +90,25 @@ function Buffer(subject, encoding) {
|
||||
|
||||
function SlowBuffer(length) {
|
||||
length = ~~length;
|
||||
var b = new Buffer(undefined, length);
|
||||
var b = new NativeBuffer(length);
|
||||
alloc(b, length);
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
// Bypass all checks for instantiating unallocated Buffer required for
|
||||
// Objects created in C++. Significantly faster than calling the Buffer
|
||||
// function.
|
||||
function NativeBuffer(length) {
|
||||
this.length = length;
|
||||
}
|
||||
NativeBuffer.prototype = Buffer.prototype;
|
||||
|
||||
|
||||
// add methods to Buffer prototype
|
||||
buffer.setupBufferJS(NativeBuffer, internal);
|
||||
|
||||
|
||||
// Static methods
|
||||
|
||||
Buffer.isBuffer = function isBuffer(b) {
|
||||
@ -386,7 +390,7 @@ Buffer.prototype.slice = function(start, end) {
|
||||
if (end < start)
|
||||
end = start;
|
||||
|
||||
var buf = new Buffer();
|
||||
var buf = new NativeBuffer();
|
||||
sliceOnto(this, buf, start, end);
|
||||
buf.length = end - start;
|
||||
if (buf.length > 0)
|
||||
|
@ -124,19 +124,13 @@ Local<Object> New(Handle<String> string, enum encoding enc) {
|
||||
}
|
||||
|
||||
|
||||
// TODO(trevnorris): these have a flaw by needing to call the Buffer inst then
|
||||
// Alloc. continue to look for a better architecture.
|
||||
Local<Object> New(size_t length) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(length <= kMaxLength);
|
||||
|
||||
Handle<Value> argv[2];
|
||||
// this is safe b/c Undefined and length fits in an SMI, so there's no risk
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
Local<Value> arg = Uint32::NewFromUnsigned(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, 1, &arg);
|
||||
|
||||
// TODO(trevnorris): done like this to handle HasInstance since only checks
|
||||
// if external array data has been set, but would like to use a better
|
||||
@ -163,12 +157,8 @@ Local<Object> New(const char* data, size_t length) {
|
||||
|
||||
assert(length <= kMaxLength);
|
||||
|
||||
Handle<Value> argv[2];
|
||||
// this is safe b/c Undefined and length fits in an SMI, so there's no risk
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
Local<Value> arg = Uint32::NewFromUnsigned(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, 1, &arg);
|
||||
|
||||
// TODO(trevnorris): done like this to handle HasInstance since only checks
|
||||
// if external array data has been set, but would like to use a better
|
||||
@ -197,12 +187,8 @@ Local<Object> New(char* data,
|
||||
|
||||
assert(length <= kMaxLength);
|
||||
|
||||
Handle<Value> argv[2];
|
||||
// this is safe b/c Undefined and length fits in an SMI, so there's no risk
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
Local<Value> arg = Uint32::NewFromUnsigned(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, 1, &arg);
|
||||
|
||||
smalloc::Alloc(obj, data, length, callback, hint);
|
||||
|
||||
@ -215,12 +201,8 @@ Local<Object> Use(char* data, uint32_t length) {
|
||||
|
||||
assert(length <= kMaxLength);
|
||||
|
||||
Handle<Value> argv[2];
|
||||
// this is safe b/c Undefined and length fits in an SMI, so there's no risk
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
Local<Value> arg = Uint32::NewFromUnsigned(length, node_isolate);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, 1, &arg);
|
||||
|
||||
smalloc::Alloc(obj, data, length);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user