V8 Internals - Handling of Anonymous Functions - javascript

For the full story, check out my other question.
Basically, I had asked if it were more efficient to use named functions in the socket handlers for the following code:
var app = require('express').createServer()
var io = require('socket.io').listen(app);
app.listen(8080);
// Some unrelated stuff
io.sockets.on('connection', function (socket) {
socket.on('action1', function (data) {
// logic for action1
});
socket.on('action2', function (data) {
// logic for action2
});
socket.on('disconnect', function(){
// logic for disconnect
});
});
The overall answer was yes (see the above link for more details), but the following comment was posted by ThiefMaster:
I'm not familiar with V8 internals but it might be smart enough to compile the function once and re-use it everytime, just with a different scope attached.
So now that's my question. Is V8 smart enough to compile anonymous functions once and reuse them with different scopes in situations where anonymous functions ordinarily lead to several function instances being created? For example, above I would expect the handler for the connection event to be created once but the handlers for action1, action2, and disconnect to be created for each connection. In the other question this was solved with named functions but I am more interested if this is necessary in V8 or if it will do some optimizations.

Yes. I asked a very similar question (related in my case to creating functions from within a constructor function) on the V8 mailing list. I got the reply that the function's code is "...normally reused...", even though there's a separate function object each time (as required by the spec).
Note, though, that your question has nothing to do with whether the function is named or anonymous. The function in your example could have a name:
io.sockets.on('connection', function handleConnection(socket) {
socket.on('action1', function (data) {
// logic for action1
});
socket.on('action2', function (data) {
// logic for action2
});
socket.on('disconnect', function(){
// logic for disconnect
});
});
That uses a named function expression, which is perfectly valid and handled correctly by V8. (Sadly, it's not handled correctly by IE8 and earlier, which create two completely different functions at totally different times. But as you're using V8, you don't have to worry about that.)

Related

jQuery (or clean JS) - add callback to any function-parameter

What I want looks like this:
function bindFunctions(bindFunction, callbackFunction) {
// Add binding so that I can call the callbackFunction if the bindFunction is called
}
function log(message) {
console.log(message);
}
function notifyUser() {
alert('Something');
}
bindFunctions(log, notifyUser);
log('Error'); // Now the notifyUser-functions should be called and "Something" printed to the alert-box
bindFunctions($('.element').click, function() {/* CODE */}); // Or this: but I don't know if this is even possible because this is not the event-function but the binding-function of the click-event
Important: I have no influence on the bindFunction so it's not possible to implement a trigger there.
It's an attachment of a callback on any kind of existing function. Do you know how or if this is possible?
I believe you're looking at it the wrong way. What you need is some good old dependency inversion. Whatever code needs log has to receive it from a higher-level component (e.g. the composition root of your application). You're then free to implement a straightforward wrapper that calls notifyUser and inject it instead of the actual log.
I've linked some articles taking an OO perspective, but feel free to translate to a more functional model (the approaches are equivalent). In your case, you're using closures (which are, under a certain light, "equivalent" to objects with a single anonymous method).
The way you have to do to add a callback to a function is this:
var foo = function(number, callback){
number += 2;
callback(number);
}
foo(2, function(result){
window.alert(result)
});
https://jsfiddle.net/6dpz88md/
Good luck

Optimizing 'Mediator' pattern with dynamic events in JavaScript (V8)

I'm looking for an elegant way to build an event-driven architecture where modules (scripts) are completely independent and decoupled from each other and rely only on Mediator for communication. Let's consider typical example:
var SomeModule = function () {...};
SomeModule.init = function ()
{
Mediator.register ('SomeEvent', this.onSomeEvent, this);
Mediator.register ('OtherEvent', this.onOtherEvent, this);
};
SomeModule.onSomeEvent = function (data)
{
var x = data.x;
var y = data.y;
// ........
Mediator.dispatch ('ThirdEvent', {name: 'Liza', gender: 1});
// now all modules registered for 'ThirdEvent' will get their callbacks executed
};
Typical Mediator operates as a dictionary routing calls from event name to according callback array to execute callbacks from. Now the problem lies in optimization: Mediator.dispatch (...) introduces dynamic objects and therefore polymorphic code which will remain slow and unoptimized when executed in V8. Some events will be fired 60 times per second and will have multiple callbacks, so it will surely benefit from optimizations.
What is the most elegant way to make this code monomorphic without introducing large boilerplate code for every new event?
EDIT: replaced .bind(this) with supplying this as context param as suggested in the comments.
60 times per second for this sort of operation is nothing.
That said if you want to optimize it, the most obvious bottleneck here will be definitely calling a function created using the native .bind function. You should always (I am not joking about always)use a homemade bind as the first thing when optimizing:
function bind(fn, ctx) {
return function() {
return fn.apply(ctx, arguments);
};
}
This doesn't do the same thing as Function.prototype.bind at all, which is the point: it does exactly what you would want bind to do and nothing more.

Javascript - How to save a reference to "this" for access in named function callback using prototype pattern

I am having problems getting a reference to a javascript object implemented with the
prototype pattern within a callback. The callback is from a 3rd party component
I utilize within my object. The 3rd party object connects to a message bus.
The following pseudo code shows how I started (The real code for this is working)
var mb = require('MsgBus')
TestClass = function() {
this.messagebus = new mb.MsgBus();
this.messagebus.connect(function(err) {
if(err)
console.log("Error connecting");
else
console.log("Connected");
});
}
But then I wanted to have it automatically retry connecting if the callback reports
an error. I cannot just put another line if the if(err) block that
says "this.messagebus.connection" because I would have to add another anonymous
method for that connect callback and it would just go on and on. So, I want to
split out the callback logic to a named function like this
var mb = require('MsgBus')
TestClass = function() {
this.messagebus = new mb.MsgBus();
this.messagebus.connect(msgBusConnectCallback);
}
function msgBusConnectCallback(err) {
if(err)
this???.messagebus.connect(msgBusConnectCallback);
else
console.log("Connected");
});
}
The callback function gets called, but I cannot figure out how to get a reference
to the object to call connect again. I've also tried to make the callback a
prototype function of the object, still no reference. I cannot create a variable
in the global scope to maintain "this" because the user of this class may
create multiple instances of the class. I am fairly new to JavaScript so I don't
know if I'm just missing something or if I need to take a different approach
altogether. I would appreciate any help and/or direction.
this.messagebus.connect.apply(this, [msgBusConnectCallback]);
I finally figured out the answer, the correct syntax is
this.messagebus.connect(msgBusConnectCallback.bind(this));

Calling functions on socket message (socket.io/node.js)

When I start a new instance of GameServer, it sets up the socket and listeners as follows.
var GameServer = function() {
this.player = new Player();
var that = this;
// Setup sockets and listeners
var socket = io.listen(8000);
socket.sockets.on('connection', function(client) {
client.on('message', that.onSocketMessage);
client.on('disconnect', that.onSocketDisconnect);
});
}
I then have two prototypes GameServer.prototype.onSocketMessage & onSocketDisconnect.
I have two problems with the current code:
Using that = this and the closure? function. Looks ugly.
When onSocketMessage is called, the idea is it works out what the message is then calls another function within GameServer. Only this isn't possible as now this belongs to the socket.io system. See below:
...
function onSocketMessage() {
this.player.move();
}
this.player is no longer available as this. is no longer part of GameServer.
Should my socket setup and message passing be handled outside of GameServer function and prototypes?
Or how else could I resolve this?
Cheers
EDIT
Ok so I have tried this and it works but looks pretty ugly I think:
var socket = io.listen(8000);
socket.sockets.on('connection', function(client) {
client.on('message', function (data) {
that.onSocketMessage(this, that, data);
});
client.on('disconnect', function() {
that.onSocketDisconnect(this, that);
});
});
Can it be improved upon?
Two things that may help. Thing the first:
You can modify a function's vision of this using the bind method.
socket.sockets.on('connection', function(client) {
client.on('message', this.onSocketMessage);
client.on('disconnect', this.onSocketDisconnect);
}.bind(this));
Notice the call to bind(this) at the end of the function; this instructs JavaScript to create a closure for you, making whatever this is outside the function, this inside the function. (If you wanted to make this inside the function, say, MySomething, you could just as easily call bind(MySomething), though bind(this) is the most common use).
Thing the second:
You can store data in a Socket.IO socket. So, for example, if one socket is always associated with a player, you can do
socket.set('player', player, function() {
// callback is called when variable is successfully stored
console.log('player has been stored');
});
// and later
socket.get('player', function(err, player) {
// callback is called either with an error set or the value you requested
player.move();
});
The get and set methods take callbacks because the Socket.IO data store can be set to something other than an in-memory store; for example, Redis.

javascript anonymous function garbage collection

If i have a function like this
function do(callback) {
//do stuff
callback();
}
and then I pass in an anonymous function:
do(function() { //do something else });
does that anonymous function ever get collected during the lifespan of the page? If not, how can i make it available for GC?
do I have to do this?
var h = function() { //do something };
do(h);
delete h;
Do I even have to worry about this? I am building a web app that has a long lifespan, makes a lot of ajax calls keeps objects for a while and doesn't really require a page refresh to navigate thru. So I'm trying to figure out if I might fall into a memory leak monster.
The only reference to the anonymous function is the function argument, and that disappears when the function finishes, so your callback will be available for garbage collection after that. Except when something else gets a reference to it, which can happen easily with closures:
function doo(callback) {
$.get(url, function() {
// callback is visible here!
});
callback();
}
doo(function() { /* do something else */ });
callback (along with the whole scope created by calling doo) must stay in the memory, because the inner function can reference it through the closure; it can only be garbage collected when the inner function is garbage collected, and since that function is a property of the jqXHR object, that object must be garbage collected before that, and who knows when that will happen...
Update You can avoid unnecessary closures by not defining your functions inside other functions:
var func = function() {
// callback is not visible here
}
function doo(callback) {
$.get(url, func);
callback();
}
doo(function() { /* do something else */ });
Watch out for circular references, otherwise the GC for the browser will clean those up. Closures make it really easy to create a circular reference, and that might be trapped in memory even if you browse away from the page that created it. So, web applications that stay on-screen for long periods of time are especially vulnerable.
Check out the section "Memory leaks" here: https://developer.mozilla.org/en/A_re-introduction_to_JavaScript.
I've designed quite a few static-page web applications. I've found that even when you don't have to clean up objects and event handlers (ie you're sure there is no circular reference), it can't hurt. It usually only adds a couple of extra lines of code, and it keeps memory use and efficiency at the forefront of your mind as you write your code. This is something of a shift for web developers because we usually don't have to think about this kind of thing very much when creating a website.

Categories

Resources