Serializing/storing closures

879 views
Skip to first unread message

Jacob Rothstein

unread,
Jun 8, 2010, 4:09:19 PM6/8/10
to nod...@googlegroups.com
Hi all,
This is a totally naïve question coming from someone who doesn't
understand the inner workings of node/v8. Is it possible to serialize
a closure, including bound scope? For now, I'm not particularly
concerned with how compact the serialized representation is. Is it
possible?

For an example use case, I'd like to be able to take a function with
bound vars, run it through this magic serialization engine, throw it
into a queue, and have another worker on another machine deserialize
and execute it. Sound interesting?

Happy nodeing,
–Jacob

inimino

unread,
Jun 8, 2010, 4:35:02 PM6/8/10
to nod...@googlegroups.com
On 2010-06-08 14:09, Jacob Rothstein wrote:
> For an example use case, I'd like to be able to take a function with
> bound vars,

Free variables?

> run it through this magic serialization engine, throw it
> into a queue, and have another worker on another machine deserialize
> and execute it. Sound interesting?

The reason to use a closure, as opposed to just a self-contained
JavaScript function, is that the closure can modify the state of
variables in the enclosing scope. Once you serialize it, that
presumably won't be the case anymore, so what's the benefit?

--
http://inimino.org/~inimino/blog/

Jacob Rothstein

unread,
Jun 8, 2010, 4:45:46 PM6/8/10
to nod...@googlegroups.com
Likely, my vocabulary was wrong. I want to serialize a javascript
function along with it's execution context.

var outside = 'world'
, fn = function (argument) { return [argument, outside].join (' ') }
fs.writeFile ('serialized.fn', magicSerializer.serialize (fn))

---
and somewhere else with no shared memory,
fs.readFile ('serialized.fn', function (err, data) {
magicSerializer.deserialize (data) ('hello') //=> 'hello world'
})

Is that more clear?

–Jacob

> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>
>

Marak Squires

unread,
Jun 8, 2010, 4:48:22 PM6/8/10
to nod...@googlegroups.com
Just use .toString(), +, and eval(). 

^_^

Scott Taylor

unread,
Jun 8, 2010, 4:58:12 PM6/8/10
to nod...@googlegroups.com
On Jun 8, 2010, at 4:48 PM, Marak Squires wrote:

Just use .toString(), +, and eval(). 

That won't save the evaluation context.  Is there a native way to get it in node?

Scott

Marak Squires

unread,
Jun 8, 2010, 5:00:41 PM6/8/10
to nod...@googlegroups.com
/me was half joking

Ryan Gahl

unread,
Jun 8, 2010, 5:08:26 PM6/8/10
to nod...@googlegroups.com
You'd have serialize the entire global namespace to start with... and then make sure you serialize all other upstream contexts that the closed over scope has handles to... ugh/shudder/boo/hiss...

To even be feasible without having to parse (with what could only be brittle logic) the function's string representation from js to figure out how to traverse and serialize all upstream scopes/objects, I'd have to assume it would be at the C++ level in the interpreter's AST/traces/low-level hoobly-hoo.... 

To get this working, in a generic sense, my guess is that it would be approximately a ridiculous amount of effort, and I can't imagine in my wildest dreams what benefits you'd receive vs marshalling relevant data to a well-defined service instead.

Ben Noordhuis

unread,
Jun 8, 2010, 5:09:10 PM6/8/10
to nod...@googlegroups.com
On Tue, Jun 8, 2010 at 22:09, Jacob Rothstein <jacob.r...@gmail.com> wrote:
> For an example use case, I'd like to be able to take a function with
> bound vars, run it through this magic serialization engine, throw it
> into a queue, and have another worker on another machine deserialize
> and execute it.  Sound interesting?

Interesting question, yes. After giving it a few minutes thought, I
don't think there is a reliable way to do this. In the example below,
what would you expect to be actually serialized? I pained my mind but
couldn't come up with a good answer.

var foo = 'bar', bar = 'baz';
function x() { return window[foo]; } // should return 'baz'

Louis Santillan

unread,
Jun 8, 2010, 5:21:13 PM6/8/10
to nod...@googlegroups.com
On Tue, Jun 8, 2010 at 2:08 PM, Ryan Gahl <ryan...@gmail.com> wrote:
> To get this working, in a generic sense, my guess is that it would be
> approximately a ridiculous amount of effort, and I can't imagine in my
> wildest dreams what benefits you'd receive vs marshalling relevant data to a
> well-defined service instead.

FYI, SpiderMonkey has this
(http://mxr.mozilla.org/mozilla-central/source/js/src/jsxdrapi.h).

-L

Dean Landolt

unread,
Jun 8, 2010, 5:23:32 PM6/8/10
to nod...@googlegroups.com
On Tue, Jun 8, 2010 at 4:58 PM, Scott Taylor <sc...@railsnewbie.com> wrote:

On Jun 8, 2010, at 4:48 PM, Marak Squires wrote:

Just use .toString(), +, and eval(). 

That won't save the evaluation context.  Is there a native way to get it in node?


Don't write your functions that depend on free vars if you want them to serialize. Then, just use json-ext instead of json and you're in business:


Persevere's been doing this forever to shuttle functions along with objects back and forth between client and server. Works just fine, but as Ryan pointed out, you'll never be able to capture the free vars.

Mikeal Rogers

unread,
Jun 8, 2010, 5:39:41 PM6/8/10
to nod...@googlegroups.com
Agreed.

Trying to serialize the free variables is a leaky abstraction because
you won't be able to tell when they change, and even if you could
notify the clients of the change you'll hit aweful side effects when
clients are competing for setting the same state in the free space.

Bad, bad, bad idea. Don't do this.

-Mikeal

Jacob Rothstein

unread,
Jun 8, 2010, 7:08:20 PM6/8/10
to nod...@googlegroups.com
Wouldn't it be neat to be able to offer developers a tool that
magically distributes execution across workers/machines without any
restrictions on how the code is written? I think that would be
ridiculously powerful, and perfect for node. In some circumstances
this could be better than forking, since it could cross machine
boundaries.

--

I understand that you wouldn't be able to track changes or make
changes back *into* the original context, but that's ok; it would be a
something like a snapshot of state. In fact, the intent would be to
execute the function with the free variable state at the time of
serialization, even if values have since changed.

I understand there would be things difficult/impossible to serialize,
like file handles & sockets. I must admit I expected those issues to
be what people brought up, but a few limitations like that don't seem
so horrible.

Is this really impossible, or is it just difficult/intimidating?

Thanks for all the feedback,
–Jacob

Timothy Caswell

unread,
Jun 8, 2010, 7:11:51 PM6/8/10
to nod...@googlegroups.com
I assume it's possible at the V8 layer (though likely difficult) since the web inspector has access to this kind of stuff. I think people are more saying it's a bad idea generally.
It may even be possible to copy around file descriptors across processes (within the same machine of course).

Correa Diego

unread,
Jun 8, 2010, 7:52:39 PM6/8/10
to nod...@googlegroups.com
I find this a facinating idea, despite its spaghetti guideline.

I guess, the fact of context serialization must be deterministically driven across the network for reliable re-execution in the context given.


2010/6/8 Timothy Caswell <t...@creationix.com>

Dean Landolt

unread,
Jun 9, 2010, 6:08:37 PM6/9/10
to nod...@googlegroups.com
On Tue, Jun 8, 2010 at 7:52 PM, Correa Diego <algor...@labormedia.cl> wrote:
I find this a facinating idea, despite its spaghetti guideline.

I guess, the fact of context serialization must be deterministically driven across the network for reliable re-execution in the context given.


It turns out it may actually be possible. Matt Podwysocki with Microsoft was telling me last night at beerjs (another awesome voodootikigod extravaganza) that Microsoft's taking a swing at this -- who knows if they'll get it right but I'd love to see it.

Sami Samhuri

unread,
Jun 10, 2010, 7:31:04 PM6/10/10
to nodejs
If this is possible it'll be one more step towards some pretty useful
Erlang functionality. I'd love to have something like this, going to
have to experiment with json-ext.

-s

cwolves

unread,
Jun 10, 2010, 9:17:58 PM6/10/10
to nodejs
I fail to see why you would want to do this... Why not just pull any
dependencies into an object and serialize the object??

-Mark

On Jun 8, 1:09 pm, Jacob Rothstein <jacob.rothst...@gmail.com> wrote:

Jacob Rothstein

unread,
Jun 11, 2010, 12:01:02 AM6/11/10
to nod...@googlegroups.com
I don't think there's anything wrong with that; in fact I'm currently
using a redis-backed task queue that works exactly like that. One
type of process serializes and enqueues the name of the function to
call and any arguments and the other side loads up the file that
contains the function and apply()s it with the provided arguments.
Worker machines have a copy of the same code as the task-creation
machines.

This works great, but I think node could have an even slicker form of
distributed computing.

I believe serializing execution context would allow you to do this
with anonymous functions. You could wrap nearly any block of code in
your app with "distribute (function () { ... })" and it could be sent
to another process or machine. The worker machines wouldn't need to
know anything about your app, because they'd get anything they needed
along with the function.

Locally, forking/worker interfaces could take advantage of this and
instead of forking a particular predefined static file, they could
fork an anonymous function, much like ruby's Kernel.fork. Imagine
"fork (function() { ... })" just magically executing that code in a
subprocess.

–Jacob

jbaron

unread,
Jun 11, 2010, 3:50:51 AM6/11/10
to nodejs
I guess the best solution would be continuation support in V8, just
like Rhino has it right now.
Then you would be able to start, stop and serialize JavaScript
execution.

When I was using Rhino, there were a few people using it exactly as
you propose.
However the few times this topic came up on the v8 mailing list, the
answer was always no (
I guess this would also be very difficult to implement if you have a
lot of the optimizations like V8 does).

Peter

Bradley Meck

unread,
Jun 11, 2010, 8:59:53 AM6/11/10
to nodejs

After a little digging, yes you can get them but I am not doing
something right as it is exiting silently, however, it requires v8-
debug.h. http://gist.github.com/434441

Alexander Mills

unread,
Nov 6, 2016, 5:12:50 PM11/6/16
to nodejs, jacob.r...@gmail.com
This would be fairly easy to do.

What you need to do is create a function that declares exactly what it depends on, then, you manually serialize everything in the origin, even the 
"free vars"


(function outer(foo,bar,baz){     // foo, bar, and baz are injected JSON strings

    return function yourSerializedFunction(){
         
             //foo, bar, and baz are available here, but you need to call JSON.parse on them

    }

})( 

  '{"foo":"is-serialized"}',
   '{"bar":"is-serialized"}',
   '{"baz":"is-serialized"}',

)

the above would have to happen in the origin

you're welcome :)
Reply all
Reply to author
Forward
0 new messages