[HN Gopher] Supercharge Your Node.js with Rust
       ___________________________________________________________________
        
       Supercharge Your Node.js with Rust
        
       Author : skwee357
       Score  : 90 points
       Date   : 2021-10-24 09:49 UTC (13 hours ago)
        
 (HTM) web link (yieldcode.blog)
 (TXT) w3m dump (yieldcode.blog)
        
       | rsgo1 wrote:
       | Small improvement: The call to unwrap() in fibonacci_api() can be
       | replaced by `?` because JsResult is just a fancy
       | std::result::Result
        
         | skwee357 wrote:
         | You are right. I'm a messy person when it comes to `?` and
         | `.unwrap()`
        
       | dherman wrote:
       | Neon maintainer here, happy to answer any questions folks might
       | have!
       | 
       | It's a pretty exciting time for Neon. We're nearly feature-
       | complete for a 1.0 release, which will come with a bunch of
       | benefits and should help us build momentum for future
       | improvements:                 * No more legacy backend -- just
       | one simple and clean way to use Neon, fully audited for safety.
       | * Strong ABI and API stability guarantees.       * Convenient
       | APIs for general-purpose multithreading and creating custom async
       | Node events.       * Ergonomic and modern use of JS promises,
       | which interact beautifully with async Rust code.
       | 
       | Some of the things I'm looking forward to exploring post-1.0 is
       | even more ergonomics and performance improvements.
        
         | gravypod wrote:
         | Is there a way to generate automatic bindings for rust/js code
         | from the AST of the language and a list of definitions to
         | specify? I'm imaging how powerful a Bazel ruleset for this
         | could be. Something like                 js_rust_library(...
         | defs = ["someFunction"] ...)
        
           | dherman wrote:
           | That's a cool idea! The closest thing today is probably neon-
           | serde, a cool community library that lets you generate
           | bindings from lightweight Rust annotations:
           | https://docs.rs/neon-serde2/0.8.0/neon_serde2/
           | 
           | Another thing I'd love to explore is using TypeScript
           | declarations (e.g. from a .d.ts file) to auto-generate
           | bindings.
           | 
           | If you're interested in playing with any of these ideas feel
           | free to hop onto our community Slack and chat!
        
         | ukulele wrote:
         | Thank you for building it! I haven't kicked the tires yet, but
         | as a node developer, this feels like the future: we can move
         | fast with node when it makes sense, and get rust level
         | performance when we need to. Best of both worlds!
        
         | skwee357 wrote:
         | I just wanted to say: Thank you! Neon is great!
        
         | flohofwoe wrote:
         | Did you consider compiling to WASM/WASI, and if yes, what were
         | the reason to go with native DLLs?
        
           | skwee357 wrote:
           | I assume this question was directed at me (author of the
           | post).
           | 
           | I've considered it. But honestly, I don't know a lot about
           | WASM (I should explore it more), so I haven't compiled it to
           | WASM. Maybe some members of the community can provide more
           | insights.
           | 
           | It is definitely something I'll try to check at some point
           | later.
        
             | dherman wrote:
             | In case it was directed at me, I'll say yes, it's on my
             | mind, but my first goal was to have the full power of the
             | entire OS facilities, the full Cargo ecosystem, and full
             | native performance with the safety of Rust. That said, I
             | think wasm has still only just begun to take off and it's
             | on my radar.
        
       | Ginden wrote:
       | > And yet, I rarely hear people suggest or even evaluate the
       | solution of embedding a native module that most of the times will
       | be faster.
       | 
       | Because there's rarely a real benefit to this approach.
       | 
       | I have yet to found use case where C/C++/Rust library is useful
       | AND spawning process to do heavy work is not a viable option AND
       | JS-only library won't work.
       | 
       | I can think basically only about communication with external
       | resource like database.
        
         | isabellat wrote:
         | We're doing exactly this in our language libraries for Tangram.
         | Our core machine learning code is written in Rust and we use a
         | native add-on so people can make predictions directly from
         | their javascript apps. In Python, this is incredibly common:
         | NumPy, LightGBM, XGBoost are written in C/C++ and exposed to
         | Python.
        
         | eyelidlessness wrote:
         | A really common use case that comes to mind immediately:
         | parsing and AST transforms. Quite common in build tooling,
         | quite noticeable performance difference as evidenced by SWC.
         | (ESBuild doesn't expose its AST, but it's also quite a lot
         | faster than comparable plain JS at what it does expose in its
         | JS interface).
        
           | trinovantes wrote:
           | The performance difference between webpack and esbuild is
           | like night and day
        
           | Ginden wrote:
           | I wrote about use case where "spawning process to do heavy
           | work is not a viable option". ESBuild DOES spawn process to
           | do heavy work.
           | 
           | https://github.com/evanw/esbuild/blob/11d7eacd491c94d2aa23cd.
           | ..
        
         | wruza wrote:
         | _I can think basically only about communication with external
         | resource like database._
         | 
         | And when it is a database, all the benefits of a compiled
         | language turn into just a fancy no-brainer wrapper which still
         | sucks because of "impedance mismatch". It would be nice if that
         | was true jit-integrated rust or at least C ffi, which one could
         | call directly from js. But I don't think that v8 will get such
         | capability in observable future.
        
       | vaughan wrote:
       | NAPI-RS is another option to Neon. It's faster and has a new
       | feature in beta that automatically does the type wrapping for
       | you.
        
         | skwee357 wrote:
         | Thanks for the suggestion! NAPI-RS does look cleaner than Neon.
         | I wonder what's the difference though. Do you know maybe? It
         | looks like NAPI-RS Docs does not list any meaningful
         | differences.
        
           | dceddia wrote:
           | I've been using NAPI-RS and I like it a lot so far. The
           | feature that caused me to switch was callbacks -
           | specifically, I wanted to pass a JS callback to Rust, and
           | have Rust call it repeatedly. I couldn't figure out how to do
           | that with Neon, but Napi has support and docs for it.
           | 
           | One difference is that NAPI-RS uses Node's N-API for calling
           | Node, and Neon has a mix of N-API and v8 backends. I'm not
           | sure if this is the main reason behind the speed difference
           | or not.
        
       | trinovantes wrote:
       | > handle.value(&mut cx) as i32
       | 
       | What happens when the user in JS land passes in an incorrect data
       | type? Does it segfault? Does it truncate the first 32 bits?
        
         | brundolf wrote:
         | If they don't pass a number at all, looks like cx.argument()
         | will return a Result::Err (which in the example will panic
         | because of the unwrap(), but can instead be bubbled up as
         | another commenter pointed out here:
         | https://news.ycombinator.com/item?id=28977697)
         | 
         | JsNumber::value() then returns an f64 to encapsulate all
         | possible JS numbers, and `as i32` is just casting that float
         | into an int. The exact behavior for this cast is that a) any
         | fractional component will be dropped, and b) if the number is
         | larger than the destination type, the destination's maximum
         | value will be used. Both of these behaviors could of course be
         | controlled by adding logic, like an explicit call to .round()
        
         | skwee357 wrote:
         | As @brundolf said above me, it will return Error because I
         | explicitly downcast it to `JsNumber` and unwrap the result. So
         | from JS side you'll get an error.
         | 
         | Obviously, you should handle such cases properly.
        
       ___________________________________________________________________
       (page generated 2021-10-24 23:02 UTC)