-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
Avoiding 10 future regrets for deno #241
Comments
@jorangreef Thank you for voicing these. I agree with you everywhere.
Absolutely - it has been a major design goal. Thanks to modern V8 support of ArrayBuffers and protobufs this is very possible.
I would have disagreed with you years ago, but I do agree now. (I thought to best support Windows was to use IOCP, which preallocates buffers. But these days fast polling is available on windows, so it makes sense to expose a non-blocking API and leave the alloc to users.
Yes, I am also very concerned about the double GC that will come with Go. I'm also concerned with how non-minimal Rust is. I'm still researching it... |
While I am fairly sympathetic to this idea, a few counterpoints the record.
Very much yes.
While I agree that node's support for off-the-main-thread data processing is severely lacking, I am not convinced that moving work to the thread pool is really the solution. A counterexample would be gzip - it can be done in the thread pool in node, now people expect it to be effectively free (see e.g. nodejs/node#8871).
I agree we screwed up a bit in node sometimes (e.g. LCD approach in fs.watch really gave us worst-of-both-worlds). However I stand by our general approach -- trying to reconcile the differences between platforms in order to expose a single API that works everywhere. Otherwise you end up in the situation that software is effectively never portable, because platform-specific APIs sneaks in without the developer being aware of it. It may have taken a while to add I'll look into what electron does differently.
Agree on all that! |
I think I have clear up a misconception here - libuv doesn't preallocate buffers for incoming data, not even on windows. It used to have an option to do this for the first N connections, but this feature was never used in node.js (in other words, N=0). Instead, it always calls two callbacks in rapid succession (alloc_cb to ask the user for a buffer, and read_cb to return the buffer to the user).
The practical difference here is that polling is now also available for other events - incoming connections, outgoing data.
I think the dilemma is more about whether you want to provide a single stream API (that also works for files) vs stay close to the Berkeley sockets abstraction. |
I still think the GC in Go is not ideal, but then again Rust's syntax is not the most RSI friendly. Zig might be the sweet spot: https://github.com/ziglang/zig/wiki/Why-Zig-When-There-is-Already-CPP%2C-D%2C-and-Rust%3F |
Funny that this came up when I searched for Flow... Flow is a better typed Js then Typescript. Forcing TS support is a regret in the making |
@rayfoss I like flow, but its ecosystem and supports are far less than ts. |
It'd be brilliant if deno native modules are WASM with WASI. Then we free up the ecosystem to use various languages for the plugins. |
How's flow? |
Supported using the syntax: #[arraybuffer] buffer: &[u8] (or &mut [u8]). All buffer types supported by #[buffer] are supported by #[arraybuffer]. This is slightly slower than typed arrays during fastcalls because we need to extract the data pointer from the underlying v8 ArrayBuffer handle.
@ry Thanks for deno! Your goals for deno are spot on.
Just wanted to share some thoughts I've had working with Node.
Interfaces should allow for zero-copy and leave memory allocation to the user as much as possible, e.g. suppose deno ever adds a core crypto api (and hopefully it never will!), but then a cipher method would allow the user to pass in not just a source buffer, but also a target buffer and a target buffer offset.
Ideally, sockets should never allocate buffers, streams should always be pull-only (instant flow control that way), and reading from a stream should always support reading into a user-supplied target buffer (at a target offset).
Propagate the idea of a single-threaded event loop control plane with a multi-core data plane, much more than Node has done. Node has sometimes had a tendency to conflate the two, so people end up doing all their crypto in the event loop without regard to throughput. Sometimes it makes sense to avoid threadpool overhead (e.g. hashing 32 bytes shouldn't be in the threadpool), but most of the time things like base64, hex, string encoding etc. should be able to run in the threadpool where it makes sense (e.g. decoding a 10 MB base64 MIME attachment), and should be async by default.
Make deno a superset of all supported platforms, not a leaky lowest-common-denominator. Node has sometimes wanted to normalize things across platforms far too much (e.g. force Unicode NFC everywhere - bad idea), or been slow to add file
btime
setters on platforms that support it, just because other platforms didn't. Something as simple as settingulimit
on Linux is just not possible with Node out of the box because of this kind of LCD thinking. Electron for all its faults is a good example of exposing platforms as they really are.Personally, I think Rust will be better than Go down the line for native bindings. One GC in v8 is enough!
Keep the core small. Native add ons are the way to go. Node's N-API is actually brilliant here.
Actually, that's it. Avoiding 6 future regrets should be enough!
The text was updated successfully, but these errors were encountered: