[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)