dgram: don't call into js when send cb is omitted
Speed up dgram.Socket#send()-heavy code a little by omitting the call into JS land when the user doesn't pass us a completion callback.
This commit is contained in:
parent
41ec6d0580
commit
1449739de0
29
lib/dgram.js
29
lib/dgram.js
@ -36,11 +36,6 @@ var net = null;
|
||||
|
||||
var errnoException = util._errnoException;
|
||||
|
||||
// no-op callback
|
||||
function noop() {
|
||||
}
|
||||
|
||||
|
||||
function isIP(address) {
|
||||
if (!net)
|
||||
net = require('net');
|
||||
@ -272,7 +267,10 @@ Socket.prototype.send = function(buffer,
|
||||
if (port <= 0 || port > 65535)
|
||||
throw new RangeError('Port should be > 0 and < 65536');
|
||||
|
||||
callback = callback || noop;
|
||||
// Normalize callback so it's either a function or undefined but not anything
|
||||
// else.
|
||||
if (!util.isFunction(callback))
|
||||
callback = undefined;
|
||||
|
||||
self._healthCheck();
|
||||
|
||||
@ -303,9 +301,19 @@ Socket.prototype.send = function(buffer,
|
||||
self.emit('error', ex);
|
||||
}
|
||||
else if (self._handle) {
|
||||
var req = { cb: callback, oncomplete: afterSend };
|
||||
var err = self._handle.send(req, buffer, offset, length, port, ip);
|
||||
if (err) {
|
||||
var req = {};
|
||||
if (callback) {
|
||||
req.callback = callback;
|
||||
req.oncomplete = afterSend;
|
||||
}
|
||||
var err = self._handle.send(req,
|
||||
buffer,
|
||||
offset,
|
||||
length,
|
||||
port,
|
||||
ip,
|
||||
!!callback);
|
||||
if (err && callback) {
|
||||
// don't emit as error, dgram_legacy.js compatibility
|
||||
process.nextTick(function() {
|
||||
callback(errnoException(err, 'send'));
|
||||
@ -317,8 +325,7 @@ Socket.prototype.send = function(buffer,
|
||||
|
||||
|
||||
function afterSend(err) {
|
||||
if (this.cb)
|
||||
this.cb(err ? errnoException(err, 'send') : null);
|
||||
this.callback(err ? errnoException(err, 'send') : null);
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,7 +46,15 @@ using v8::Uint32;
|
||||
using v8::Undefined;
|
||||
using v8::Value;
|
||||
|
||||
typedef ReqWrap<uv_udp_send_t> SendWrap;
|
||||
|
||||
class SendWrap : public ReqWrap<uv_udp_send_t> {
|
||||
public:
|
||||
SendWrap(Local<Object> req_wrap_obj, bool have_callback);
|
||||
inline bool have_callback() const;
|
||||
private:
|
||||
const bool have_callback_;
|
||||
};
|
||||
|
||||
|
||||
static Persistent<Function> constructor;
|
||||
static Cached<String> buffer_sym;
|
||||
@ -54,6 +62,17 @@ static Cached<String> oncomplete_sym;
|
||||
static Cached<String> onmessage_sym;
|
||||
|
||||
|
||||
SendWrap::SendWrap(Local<Object> req_wrap_obj, bool have_callback)
|
||||
: ReqWrap<uv_udp_send_t>(req_wrap_obj)
|
||||
, have_callback_(have_callback) {
|
||||
}
|
||||
|
||||
|
||||
inline bool SendWrap::have_callback() const {
|
||||
return have_callback_;
|
||||
}
|
||||
|
||||
|
||||
UDPWrap::UDPWrap(Handle<Object> object)
|
||||
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) {
|
||||
int r = uv_udp_init(uv_default_loop(), &handle_);
|
||||
@ -228,6 +247,7 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
|
||||
assert(args[3]->IsUint32());
|
||||
assert(args[4]->IsUint32());
|
||||
assert(args[5]->IsString());
|
||||
assert(args[6]->IsBoolean());
|
||||
|
||||
Local<Object> req_wrap_obj = args[0].As<Object>();
|
||||
Local<Object> buffer_obj = args[1].As<Object>();
|
||||
@ -235,11 +255,12 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
|
||||
size_t length = args[3]->Uint32Value();
|
||||
const unsigned short port = args[4]->Uint32Value();
|
||||
String::Utf8Value address(args[5]);
|
||||
const bool have_callback = args[6]->IsTrue();
|
||||
|
||||
assert(offset < Buffer::Length(buffer_obj));
|
||||
assert(length <= Buffer::Length(buffer_obj) - offset);
|
||||
|
||||
SendWrap* req_wrap = new SendWrap(req_wrap_obj);
|
||||
SendWrap* req_wrap = new SendWrap(req_wrap_obj, have_callback);
|
||||
req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj);
|
||||
|
||||
uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
|
||||
@ -328,19 +349,13 @@ void UDPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
// TODO(bnoordhuis) share with StreamWrap::AfterWrite() in stream_wrap.cc
|
||||
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(req != NULL);
|
||||
|
||||
SendWrap* req_wrap = static_cast<SendWrap*>(req->data);
|
||||
UDPWrap* wrap = static_cast<UDPWrap*>(req->handle->data);
|
||||
|
||||
assert(req_wrap->persistent().IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
Local<Value> arg = Integer::New(status, node_isolate);
|
||||
MakeCallback(req_wrap_obj, oncomplete_sym, 1, &arg);
|
||||
if (req_wrap->have_callback()) {
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
Local<Value> arg = Integer::New(status, node_isolate);
|
||||
MakeCallback(req_wrap_obj, oncomplete_sym, 1, &arg);
|
||||
}
|
||||
delete req_wrap;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user