Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transferable objects #23

Closed
Rich-Harris opened this issue Jul 7, 2014 · 8 comments
Closed

Transferable objects #23

Rich-Harris opened this issue Jul 7, 2014 · 8 comments
Milestone

Comments

@Rich-Harris
Copy link
Contributor

This is a slightly speculative issue but I thought it worth raising - do you have any plans to support transferable objects?

For anyone not familiar: transferable objects allow you to transfer an ArrayBuffer (and also a CanvasProxy or MessagePort, whatever they are!) to and from a web worker - rather than using the structured cloning algorithm, the reference to a transferable object is 'neutered' once it's transferred - the chunk of memory actually changes owner.

I'm using operative in a project that deals with large amounts of binary data. I've implemented support for transferables in my local copy of the library, and it's blazing fast. If it's useful I can tidy up the code and share it when I get a chance (it's probably not PR-worthy yet).

This is a heavily condensed illustration of how I'm using it:

projectGeometry = operative( function ( arrayBuffer ) {
  var d = this.deferred();

  float32Array = doSomeComplexMathsAndReturnATypedArray( arrayBuffer );
  d.transfer( float32Array.buffer );
}, [ 'poly2tri.min.js' ]);

// `buffer` comes straight from an xhr with responseType: 'arraybuffer'
projectGeometry.transfer( buffer ).then( function ( resultBuffer ) {
  var typedArray = new Float32Array( resultBuffer );
  doSomethingWith( typedArray );
});

An alternative API is to specify the data and the transfer list separately (which is how it works under the hood with postMessage:

w = operative( function ( foo, typedArray, anotherTypedArray ) {
  var d = this.deferred();

  /* some code happens... */

  d.transfer({ aThing: 42, anotherThing: myTypedArray }, [
    // list of objects to transfer from worker
    myTypedArray.buffer
  ]);
});

w.transfer( foo, typedArray, anotherTypedArray, [
  // list of objects to transfer to worker
  typedArray.buffer,
  anotherTypedArray.buffer
]).then( handleResult );

It's fairly easy to detect support for transferables (you just try transferring an array buffer and see if the byteLength falls to zero - article), and falling back to structured cloning works just fine.

@padolsey
Copy link
Owner

padolsey commented Aug 6, 2014

Hi -- sorry for this crazily late reply! I'll have a deeper look into this when time permits, but it definitely looks like something operative should support. I think I did consider it right at the beginning but I couldn't figure out a clear path to degradation, and wasn't sure about including non-degradable things in operative's core API. Maybe the transfers thing should be in the form of a plugin? Not sure.

If you have time to submit a PR (even messy code is ok) that'd be really great -- I'd like to experiment a bit with it.

@Rich-Harris
Copy link
Contributor Author

Will try and send a PR in the next few days, as soon as I've had a chance to do some post-launch cleanup and consolidation. The project we launched today uses the modified version I referred to above. We're using it to triangulate and project a load of geometry onto a sphere - the end result is quite chunky, and structured cloning is slower than ideal, so the input 2d geometry and the output 3d geometry are transferred as ArrayBuffers. Our version of operative exposes a property called hasTransferableSupport, but we don't actually use it - the transfer methods just fall back to structured cloning in environments that don't support transferables, so it's a fairly low-effort progressive enhancement.

@padolsey
Copy link
Owner

Congrats on the launch! Out of curiosity are you pooling workers/operatives for machines with > 1 core?

@padolsey padolsey added this to the 0.4.0 milestone Aug 29, 2014
@padolsey
Copy link
Owner

padolsey commented Oct 7, 2014

How does this look? -- https://github.com/padolsey/operative/wiki/Transfers-API (this is what I'm currently implementing for a 0.4 rc.

padolsey pushed a commit that referenced this issue Oct 7, 2014
@evanworley
Copy link

@padolsey - Looks good. One small note, I don't believe Transferable
Objects are a feature of postMessage, though that might have been one of
the earliest uses.

On Mon, Oct 6, 2014 at 11:35 PM, James Padolsey notifications@github.com
wrote:

How does this look? --
https://github.com/padolsey/operative/wiki/Transfers-API (this is what
I'm currently implementing for a 0.4 rc.


Reply to this email directly or view it on GitHub
#23 (comment).

@padolsey
Copy link
Owner

padolsey commented Oct 8, 2014

That's true -- but I meant that transferring Transferable objects via postMessage is a feature of postMessage... but that's all needlessly convoluted ... so I'll change the wording :D

@padolsey
Copy link
Owner

This is now available in 0.4.0-rc1 (via npm). Branch is 0-4-rc1.

@Rich-Harris
Copy link
Contributor Author

This is awesome! Sorry I never got round to sending that PR - probably for the best, your implementation is a good bit neater than the hacks we shipped our project with :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants