Browse Source

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.
v0.11.6-release
Ben Noordhuis 12 years ago
parent
commit
1449739de0
  1. 29
      lib/dgram.js
  2. 43
      src/udp_wrap.cc

29
lib/dgram.js

@ -36,11 +36,6 @@ var net = null;
var errnoException = util._errnoException; var errnoException = util._errnoException;
// no-op callback
function noop() {
}
function isIP(address) { function isIP(address) {
if (!net) if (!net)
net = require('net'); net = require('net');
@ -272,7 +267,10 @@ Socket.prototype.send = function(buffer,
if (port <= 0 || port > 65535) if (port <= 0 || port > 65535)
throw new RangeError('Port should be > 0 and < 65536'); 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(); self._healthCheck();
@ -303,9 +301,19 @@ Socket.prototype.send = function(buffer,
self.emit('error', ex); self.emit('error', ex);
} }
else if (self._handle) { else if (self._handle) {
var req = { cb: callback, oncomplete: afterSend }; var req = {};
var err = self._handle.send(req, buffer, offset, length, port, ip); if (callback) {
if (err) { 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 // don't emit as error, dgram_legacy.js compatibility
process.nextTick(function() { process.nextTick(function() {
callback(errnoException(err, 'send')); callback(errnoException(err, 'send'));
@ -317,8 +325,7 @@ Socket.prototype.send = function(buffer,
function afterSend(err) { function afterSend(err) {
if (this.cb) this.callback(err ? errnoException(err, 'send') : null);
this.cb(err ? errnoException(err, 'send') : null);
} }

43
src/udp_wrap.cc

@ -46,7 +46,15 @@ using v8::Uint32;
using v8::Undefined; using v8::Undefined;
using v8::Value; 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 Persistent<Function> constructor;
static Cached<String> buffer_sym; static Cached<String> buffer_sym;
@ -54,6 +62,17 @@ static Cached<String> oncomplete_sym;
static Cached<String> onmessage_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) UDPWrap::UDPWrap(Handle<Object> object)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) { : HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_udp_init(uv_default_loop(), &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[3]->IsUint32());
assert(args[4]->IsUint32()); assert(args[4]->IsUint32());
assert(args[5]->IsString()); assert(args[5]->IsString());
assert(args[6]->IsBoolean());
Local<Object> req_wrap_obj = args[0].As<Object>(); Local<Object> req_wrap_obj = args[0].As<Object>();
Local<Object> buffer_obj = args[1].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(); size_t length = args[3]->Uint32Value();
const unsigned short port = args[4]->Uint32Value(); const unsigned short port = args[4]->Uint32Value();
String::Utf8Value address(args[5]); String::Utf8Value address(args[5]);
const bool have_callback = args[6]->IsTrue();
assert(offset < Buffer::Length(buffer_obj)); assert(offset < Buffer::Length(buffer_obj));
assert(length <= Buffer::Length(buffer_obj) - offset); 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); req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj);
uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset, 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 // TODO(bnoordhuis) share with StreamWrap::AfterWrite() in stream_wrap.cc
void UDPWrap::OnSend(uv_udp_send_t* req, int status) { 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); SendWrap* req_wrap = static_cast<SendWrap*>(req->data);
UDPWrap* wrap = static_cast<UDPWrap*>(req->handle->data); if (req_wrap->have_callback()) {
HandleScope scope(node_isolate);
assert(req_wrap->persistent().IsEmpty() == false); Local<Object> req_wrap_obj = req_wrap->object();
assert(wrap->persistent().IsEmpty() == false); Local<Value> arg = Integer::New(status, node_isolate);
MakeCallback(req_wrap_obj, oncomplete_sym, 1, &arg);
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; delete req_wrap;
} }

Loading…
Cancel
Save