Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rust + Node = Neon

dherman
November 17, 2016

Rust + Node = Neon

I presented Neon, a system for writing native Node.js modules using Rust, at the Bay Area Rust Meetup.

Video at: https://youtu.be/jINMIAicaS0

dherman

November 17, 2016
Tweet

More Decks by dherman

Other Decks in Programming

Transcript

  1. N E O N
    R U S T + N O D E =

    View full-size slide

  2. A whole new generation of systems programmers…

    View full-size slide

  3. • Dip your toe in
    • Performance
    • Easy integration of native libraries
    • Hack without fear: safety first!

    View full-size slide

  4. #[macro_use]
    extern crate neon;
    use /* ... */;
    fn hello(call: Call) -> JsResult {
    Ok(JsString::new(call.scope, "hello node").unwrap())
    }
    register_module!(m, {
    m.export("hello", hello)
    });

    View full-size slide

  5. #[macro_use]
    extern crate neon;
    use /* ... */;
    fn hello(call: Call) -> JsResult {
    Ok(JsString::new(call.scope, "hello node").unwrap())
    }
    register_module!(m, {
    m.export("hello", hello)
    });
    ?

    View full-size slide

  6. init_obj
    init_prop
    set_prop
    initObject
    eventHandler
    JavaScript
    Rust
    Object::set
    setter
    V8
    GC'ed Heap
    JavaScript

    View full-size slide

  7. init_obj
    init_prop
    set_prop
    initObject
    eventHandler
    JavaScript
    Rust
    Object::set
    setter
    V8
    GC'ed Heap
    JavaScript

    View full-size slide

  8. init_obj
    init_prop
    set_prop
    initObject
    eventHandler
    JavaScript
    Rust
    Object::set
    setter
    V8
    GC'ed Heap
    JavaScript

    View full-size slide

  9. var total = 0;
    for (var i = 0, n = lines.length; i < n; i++) {
    total += wcLine(lines[i], "thee");
    }

    View full-size slide

  10. function wcLine(line, search) {
    var words = line.split(' ');
    var total = 0;
    for (var i = 0, n = words.length; i < n; i++) {
    if (matches(words[i], search)) {
    total++;
    }
    }
    return total;
    }
    280ms

    View full-size slide

  11. fn wc_line(line: &str, search: &str) -> i32 {
    let mut total = 0;
    for word in line.split(' ') {
    if matches(word, search) {
    total += 1;
    }
    }
    total
    }
    85ms

    View full-size slide

  12. fn wc_line(line: &str, search: &str) -> i32 {
    line.split(' ')
    .filter(|word| matches(word, search))
    .fold(0, |sum, _| sum + 1)
    }

    View full-size slide

  13. fn wc_line(line: &str, search: &str) -> i32 {
    line.split(' ')
    .filter(|word| matches(word, search))
    .fold(0, |sum, _| sum + 1)
    }
    lines.into_iter()
    .map(|line| wc_line(line, search))
    .sum()

    View full-size slide

  14. fn wc_line(line: &str, search: &str) -> i32 {
    line.split(' ')
    .filter(|word| matches(word, search))
    .fold(0, |sum, _| sum + 1)
    }
    lines.into_par_iter()
    .map(|line| wc_line(line, search))
    .sum()
    50ms

    View full-size slide

  15. fn wc_line(line: &str, search: &str) -> i32 {
    line.split(' ')
    .filter(|word| matches(word, search))
    .fold(0, |sum, _| sum + 1)
    }
    lines.into_par_iter()
    .map(|line| wc_line(line, search))
    .sum()
    50ms

    View full-size slide

  16. let mut buffer = call.arguments.require(scope, 0)?
    .check::()?;
    let total = buffer.grab(|data| {
    let corpus = str::from_utf8(data.as_slice()).unwrap();
    wc(&lines(corpus), "thee")
    });
    Ok(JsInteger::new(scope, total))

    View full-size slide

  17. struct Greeter {
    greeting: String
    }
    declare_types! {
    pub class JsGreeter for Greeter {
    init(greeting: String) {
    Ok(Greeter { greeting: greeting })
    }
    method hello(call: Call) {
    let scope = call.scope;
    let name = call.arguments.require(scope, 0)?.check::()?;
    let message = call.arguments.this(scope).grab(|greeter| {
    format!("{}, {}!", greeter.greeting, name)
    });
    Ok(JsString::new(scope, message).unwrap())
    }
    }
    }

    View full-size slide

  18. module! {
    export class JsGreeter for Greeter {
    init(greeting: String) {
    Ok(Greeter { greeting: greeting })
    }
    method hello(name: String) -> String {
    Ok(self.arguments.this(self.scope).grab(|g| {
    format!("{}, {}!", g.greeting, name)
    }))
    }
    }
    }

    View full-size slide

  19. module! {
    export function add1(x: i32) -> i32 {
    Ok(x + 1)
    }
    }

    View full-size slide

  20. A few caveats:
    • Currently better for apps than libs.
    • Calling from JS to Rust costs, so make it worth it.
    • I keep falling asleep in my comfy hacking chair!

    View full-size slide

  21. https://github.com/rustbridge/neon
    Thank you!

    View full-size slide

  22. I M A G E C R E D I T S
    • https://unsplash.com/photos/Niy6KKRAu1Y
    • https://www.youtube.com/watch?v=N1icEHtgb3g
    • http://www.sideshowtoy.com/collectibles/the-hobbit-gandalf-the-grey-asmus-collectible-toys-902681/
    • https://www.rust-lang.org/logos/rust-logo-512x512-blk.png
    • https://nodejs.org/static/images/logos/nodejs-new-white-pantone.png
    • https://www.flickr.com/photos/morgennebel/11854357125/in/photolist-j4wFnF-poSvWa-9F81pt-poCWZL-pwJLS8-
    o1WiLo-87zwv6-rEfLQD-9adjGY-g5WKTT-g5W4UA-psQtns-fddieS-rn4gXZ-pnjo8R-e9Ck2i-kD5gZX-CCXFqE-eb6pxd-
    g5WniL-ey9Qs1-cJofsb-6vvL1M-nRgkhR-6edC3p-kHEzPp-4zYFsi-U7wt9-fJU62F-ssgkaY-qJehyN-kUfLJx-qLndLK-
    fiHPW7-ffAfAq-ieJcgA-ieJiDo-rcvDPd-e9CptH-pwJEX2-ieJgyo-cxR34J-cgc7pj-3dBYvj-eFBMJJ-9hEsh5-avugjT-
    cgc6Wm-ieHQLr-fHDYpN
    • http://www.anonymousproductionassistant.com/wp-content/uploads/2016/10/main_freereports.jpg
    • https://www.youtube.com/watch?v=jDQaIl_1Nfk
    • https://www.youtube.com/watch?v=8ud6haTTfFY
    • https://www.disneyclips.com/imagesnewb3/images/clipcindydream.gif

    View full-size slide