10 ms·
Now I have four services running on production, all written with Rust. If it compiles, it usually works. Of course you have these late night sessions where you
by pimeys 10y ago
Now I have four services running on production, all written with Rust. If it compiles, it usually works. Of course you have these late night sessions where you write that one unwrap() because, hey, this will never return an error, right? And bam...
I'm seriously waiting that tokio train to be stable and a unified way of writing async services without needing to use some tricks with the channels or writing lots of ugly callback code. Also the native tls support is coming and the dependency hell with openssl would be gone forever.
If you need http server/client, I'd wait for a moment for Hyper to get their tokio branch stable and maybe having support for http2 by migrating the Solicit library.
- kibwen 10y agoSpeaking of HTTP clients, just yesterday the person behind Hyper announced their new high-level HTTP client crate: http://seanmonstar.com/post/153221119046/introducing-reqwest http://seanmonstar.com/post/153221119046/introducing-reqwest
- Animats 10y agoNot sure what to think of that. Does everything have to be async I/O now? How often do you need massive numbers of client connections?
- steveklabnik 10y ago1. This introduces a primarily synchronous API for now. Async will come later. All those code samples are synchronous. 2. Async I/O is an extremely hot topic in Rust right now, so it's likely that Rust people do care about it.
- dbaupp 10y agoI assume you're talking about why reqwest is necessary (i.e. why hyper is moving to async), rather than the single paragraph mentioning asynchronicity as a possible future direction for reqwest? Async I/O is important for more than just multiplexing a million requests. Hyper is moving to it for that purpose, and also because it is a more natural way for working with in-flight I/O, e.g. cancelling requests or selecting over them.
- jcrites 10y agoAsynchronous nonblocking interfaces are more general-purpose than synchronous blocking interfaces. I can't speak for this library or Rust specifically, but in my experience well-designed asynchronous libraries allow you to interact with them in a synchronous style as well, if you wish. Netty is an asynchronous, event-driven network framework for Java, and it's perfectly possible to expose synchronous blocking abstractions on top of it. The mechanism is pretty simple: the asynchronous framework exposes a future representing the result of an operation, and to provide a synchronous interface you simply block on the completion of that future before returning. Client libraries can handle this for you, providing the interface of e.g. a regular blocking HTTP client on top of Netty async IO. This approach can be convenient, since it's possible for both synchronous and asynchronous style code to coexist easily in the same application. The application designer can incrementally change parts of the application into asynchronous style as performance needs dictate. For example, you might choose to serve typical small RPC requests using blocking workers in a thread pool, but when you need to stream the content of a large file across the network you could use a separate nonblocking worker pool that interacts with both the file system and network asynchronously. The ability to interact in a blocking way via futures means that asynchronous facilities can serve both synchronous and asynchronous needs, making them the better choice for most frameworks today. While it used to be the case that async IO frameworks took a performance penalty compared to well-implemented sync IO ones, from what I understand that gap has been closed, and the highest performance frameworks are now all async IO. For example, check out the TechEmpower Web Framework Benchmarks. Most or all of the top performers use asynchronous approaches: https://www.techempower.com/benchmarks/#section=data-r13&hw=ph&test=plaintext https://www.techempower.com/benchmarks/#section=data-r13&hw=...
- Animats 10y agoYes, I know, async I/O is the new cool thing. Here's an async I/O program from 1972.[1] John Walker wrote this. EXEC 8 had the IO$ system call, which, unlike IOW$, returned immediately. A "completion routine" was called when the I/O operation finished. Note how similar those libraries are to what's used today, now that people are reading Dijkstra again. The problem, of course, is that a callback system dominates the architecture of the entire program. (When I moved from UNIVAC mainframes to UNIX, things seemed so sequential. No threads. No async I/O.) [1] http://www.fourmilab.ch/documents/univac/fang/ http://www.fourmilab.ch/documents/univac/fang/
- kbenson 10y agoSimply put, IO as accessed by the Os is asynchronous by nature. The synchronicity you are used to is a nice artifact and lie the OS tells you to make simple programming easier. Underneath, the OS is doing everything asynchronously, and just waiting until complete to return, otherwise we would be throwing away massive quantities of compute cycles waiting for IO to complete. Why let the OS and other programs running at the same time reap all that benefit? You too can program such that while you would normally be waiting for IO and some other programs was utilizing the CPU, your own cycles can be used and you can be accomplishing so much more.
- lmm 10y agoI don't think everything has to be async, but if there's ever a place to use it then it's HTTP. There are too many systems that rely on an external web service and collapse in a ball of threads if that external web service ever gets a bit slow.
- tmzt 10y agoWould it make sense to have a cargo/rustc flag to disable unwrap and friends when building for production?
- steveklabnik 10y agounwrap has legitimate use-cases, and it's not clear what "disable" it would be, as it changes the type of the thing it returns. You could write a lint to fail the build, if you want, I guess...
- Manishearth 10y agoclippy has this already :)
- bumblebeard 10y agoFor those not familiar with Clippy: https://github.com/Manishearth/rust-clippy https://github.com/Manishearth/rust-clippy It's a very useful tool; the main thing about it that annoys me is that it only works with nightly.
- tmzt 10y agoRight, it would likely use clippy but it would essentially be a --production target or profile, intended for builds where the binary will be run in production. And by 'and friends' I mean calls that panic for the same reason as unwrap, such as expect or ok. The goal is to stop code from reaching production inadvertently, not to prevent all sources of panics.
- wyldfire 10y agoBut if we accept the premise that "it's acceptable in some cases to have unwrap() in code that targets 'production'" then it wouldn't make sense to have a production profile that bars its use. The word "production" is in the global namespace and I think you want something more specific to your use case. Rather, one could define a rust coding guide for themselves that deems unwrap() inappropriate for production use. (and in that case use the lint Steve suggests).
- dep_b 10y agoIsn't if let similar to Swift's if let where it either unwraps safely or does something else? I really wish I could disable forced unwrapping as it mostly leads to mistakes by less experienced or overconfident programmers and the amount of extra code by using guard instead if you program smart is negligible.
- AsyncAwait 10y agoRust's if let is indeed inspired by that of Swift and behaves practically the same way.
- kibwen 10y agoThough Swift's `if let` is AFAIK hardcoded to their built-in optional type, whereas when Rust lifted the idea they made it work with any enum. I believe Swift recently gained `if case let` as an equivalent to how `if let` works in Rust.
- steveklabnik 10y agoAny unrefutable pattern, I believe. EDIT: whoops! I got it backwards. It's refutable, right, duh. :)
- gue5t 10y agoIf-let can be used with refutable patterns (the refutation/counterexample to the pattern is when the else case runs). Irrefutable patterns can be used with regular let.
- tomjakubowski 10y agoAny refutable pattern; for irrefutable patterns the "if let"'s pattern would always match, so it would be kinda redundant. :-)
- dep_b 10y agoIt was new in Swift 2 I think. Didn't use it yet. But it's basically a single case statement lifted from switch, nothing more. But enums and switch statements can be really complex beasts by themselves in Swift. If Rust only allows it on enums that would be extremely weird. In a switch statement I sometimes want to switch on the object, then see if I'm allowed to unwrap it to a certain class and immediately use it afterwards. Useful for parsing an array of mixed object types that should be processed differently. But I honestly think Swift allows people to write elaborate illegible codegolf-y bullshit sometimes. Sometimes the Swift compiler still chokes on too complex expressions and you need to add some explicit types or separate out in several statements what you were trying to do in one statement. Usually a good warning that your code is hard to read even by humans.
- amelius 10y ago> I'm seriously waiting that tokio train to be stable and a unified way of writing async services without needing to use some tricks with the channels or writing lots of ugly callback code By which [1] is meant, for those not knowing. [1] https://github.com/tokio-rs/tokio https://github.com/tokio-rs/tokio
- shmerl 10y agoWasn't there some other effort in Rust to enable asynchronous I/O?
- steveklabnik 10y agoThere's been a few; this one is built on top of mio, one of the most popular previous ones.
- shmerl 10y agoI meant this one which I saw mentioned recently: https://github.com/alexcrichton/futures-rs https://github.com/alexcrichton/futures-rs
- steveklabnik 10y agoAh yes. Basically, tokio is mio + futures.
- AsyncAwait 10y agotokio is not an alternative to futures, but rather a more high-level framework that builds on top of futures - both are being actively developed.