Hacker News new | past | comments | ask | show | jobs | submit login
Trying Rust for web services (wearewizards.io)
122 points by Keats on Oct 1, 2015 | hide | past | favorite | 97 comments



I've historically been very skeptical of Rust in the web application tier, but I've been playing around with it lately. It's been nicer than I've expected.

One thing this blog post points out is Rust ecosystem docs. I've been trying to find a good way to evaluate this: https://users.rust-lang.org/t/lets-talk-about-ecosystem-docu...

Other thoughts:

Crates.io, our package server, uses Rust + Ember. One thing that is really interesting about Rust in this space is memory usage: last I heard, crates.io uses a flat ~30 MB of RAM, resident. I'm used to Rails where that is... very different.

On that note, I think "Rust serving JSON + Javascript for the frontend" is a really interesting stack. I've been trying to find the time (and hopefully roping another person or two in) to build a http://jsonapi.org/ library for this purpose. I have a project where I've been using it, but I went down the "why use a library, I can generate the JSON by hand" and it's.... ugly. Serde is so much nicer.

As always with a young ecosystem, we need more libraries. For everything. It's gotten a lot better, and much of the basics are there, but sometimes, you're still going to have to write things yourself, which slows things down.

mio is gaining preliminary Windows support, and once it does, hyper will roll it in, which should significantly improve performance in many web contexts, as well.

I largely come from Ruby, where Rails was such a leap forward that people learned Ruby just to use it. I expect that if you know Rust, writing application-tier Rust will be fine, but I'm not sure it will ever see the same kind of pattern.


Hi Steve,

I don't have a login on rust-lang yet, but I wanted to add this comment regarding the documentation:

The rust-doc auto generated pages are really confusing. The sidebar generally fails to show where in the hierarchy of the API docs you are (ideally it would highlight the current page you're looking at in the hierarchy and provide the full hierarchy to give you context), the breadcrumbs don't indicate that they are links, the breadcrumbs indicate the type of the entry to the left rather than the right adding semantic confusion, and long pages tend to not have a TOC meaning you have to either search in the page or know the page structure ahead of time (probably mostly an issue for new users).

I feel like those are all simple mechanical issues that could make the auto-generated rust-docs a lot more useful.

It'd also be nice to tie non-auto generated docs into a crate's documentation, but I haven't looked into how rustdoc works so I'd guess that's possible but a lot of people don't do it.


Hey there. Thanks! Rustdoc can _certainly_ use way more improvements. Many of the things you've expressed are here: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Ais... I would love to re-write all of Rustdoc, frankly, but haven't been able to. Even just re-doing the HTML/CS/JS would be pretty great, I think. There are never enough hours in the day.

As for non-API docs, https://github.com/rust-lang/cargo/issues/739 is the tracking issue. Also great to have, also just needs someone to come along and do it.


I'm not overly familiar with Rustdoc's internals, but I would imagine that traversing type information will become much more straightforward when HIR/MIR become a reality. Is that accurate? If so, maybe that's a something for which it's worth delaying a structural overhaul.


I have no idea how rustdoc works, frankly. Parsers are one of those things that I am irrationally scared to hack on. At some point, I'll get fed up and overcome that, but it hasn't quite gotten there yet...


Is it possible to do https serving in any of the web frameworks? Last I checked (months ago) it did not seem possible. I guess a crypto and tls library would be essential to this. I think https is pretty important feature to have given http2 and whats coming down the pipe.


Iron supports it at the least( http://ironframework.io/doc/iron/enum.Protocol.html ).

And if you want to patch other frameworks or build your own: I have personally used Hyper (http-crate) with the OpenSSL crate to do Https before and I found it very easy.


As far as I know, hyper has HTTPS support, yes. We use an openssl wrapper in Cargo all the time.


Can you point me to an example? I tried looking at the cargo github repo and searched for tls but had no luck. Also searched for 443 and found it in source.rs but it was in a url canonicalization function when calling github.

I am looking for example code where I can pass in the server certificate prior to listening. Something similar in functionality to Go's http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)

Edit: typo


Cargo is a client, not a server, so that's probably where your problem finding things lies. I don't have an example handy, to be honest. Historically speaking, when deploying Rails, I would always use Nginx in front of my application server to terminate SSL anyway...

Also, the Iron docs that another commenter pointed you at looks vaguely like that call. I'm not familiar with Go's API.


What's the deal with Serde / rustc_serialize ? I've used serde mainly because I've seen mentioned a few times and saw a thread somewhere saying it was the successor of rustc_serialize.


rustc_serialize was built for the compiler itself, and not really well-designed to be an external library. But it was Good Enough for a long time. Serde is the next-gen, built from the ground up to be awesome thing.


Should there be some kind of indication of that in the crate repo or doc of rustc_serialize?


Well, it depends. Serde is still in active development, not at 1.0 yet. I don't think it's totally clear that at _this moment_, it's always better. It will be in the future, I'm just not sure that future is today.

Plus, there are other serialization libraries as well, and having the official Rust docs play favorites in the ecosystem is something we try to avoid.


Also, until Stable rust gets custom_derive, the barrier to entry for Serde is too high.


The tragedy being that rustc_serialize only gets away with this because its machinery is directly built into the compiler.


I have fully switched over to Rust to do my web backend's. I use Nickel.rs and it has worked great. The code is very succinct and fast. The only downside I have found to this is that there is no "Hot Reload" which I had with Flask(Python) and Play(Scala).

As the ecosystem grows I only expect it to get better.


Unless you are on windows, you can try cargo-watch[1] to re-compile and run your code when the source changes.

1: https://github.com/passcod/cargo-watch


I will have to give that a try. Its amazing how much hot reloading speeds up development.


    sudo apt-get install inotify-tools
and a short shell script.


Nickle.rs is at http://nickel.rs/


It's also spelled "Nickel.rs", as shown in the link ^_^


Oops, my mistake.


I have also switched to Rust for backend work.

I'm using Iron instead of Nickel. Not sure who will become more popular over time...

Because of the language (no null, bounds checking, option/result types, etc.) and borrow checker I find I rarely have to 'hot reload' or even test my code. I realize that sounds surprising. I'm not doing any HTML templating in Rust - that's better done in JavaScript on the client - so I don't have the edit/compile/test cycle for every tweak to the UI.


What was behind your decision to pick Rust? My understanding is that Rust is meant as replacement for C++ in places where C++ performance is needed (browsers, systems programming (maybe)), etc. A web server does not fall into that category, so why did you pick it?


"A web server does not fall into that category, so why did you pick it?"

That's too categorical a statement. It depends on a lot of things. Sure, there's a place in the world for PHP pages that take two or three full seconds to render, but it doesn't matter because they're doing something useful and don't get hit a thousand times per second. There's also a place for things that render in under a millisecond because they're getting hit at an incredible rate, and if they also have some sort of interdependencies then Rust can make a lot of sense.

Plus as I've said before, the whole "you're stuck in IO anyhow so who cares how fast the render code runs" dogma has sometimes gone too far. (I know you didn't say anything about that, but I'm guessing based on experience it's what lies behind your point.) My experience in switching from slow languages to fast languages, even doing the same IO, is that you do tend to see real performance gains unless your page was absolutely trivial. Slow languages really are slow in practice.


> That's too categorical a statement. It depends on a lot of things.

I didn't mean it to be. Of course there are extreme cases where GC pauses are unacceptable on a web server, but those are relatively rare. Even Google mostly uses Java (although they are heavy C++ users, is it for their web servers?).

There are always extreme cases, which is why I asked the question.

> My experience in switching from slow languages to fast languages, even doing the same IO, is that you do tend to see real performance gains unless your page was absolutely trivial. Slow languages really are slow in practice.

Slow vs. fast is not black and white. Is Go slow? Is Lua slow? I Java (on a warmed up JVM) slow?

We're talking about GC vs. non-GC languages here. Do you really see a difference in performance gains?


>Even Google mostly uses Java

I'm not so sure about that. The core services (e.g. Search, Maps, Earth, Big table, Map reduce) seem to be C++. Ads is possibly an exception.


We're talking specifically about the web application servers here. I wouldn't be surprised that something like Search is C++, it's one of the most visited pages in the world. But I haven't heard specifically that it is.

I don't think it's any secret that Java is huge Java users. If not web servers, then for what?


50% C++, 25% Java

http://qr.ae/RP7wXh

At Google's scale, the performance difference between Java and C++ can means millions of dollars in electricity alone.


That's the amount of code in their repo which covers a lot more than web application servers.

This is an unnecessary tangent though, as I've said throughout this discussions, there's extreme cases and no doubt Google is likely one of them. But we're talking about common use case, to which I still haven't seen any evidences that GC pauses are a deliberating factor.


You may already be familiar with this and are specifically concerned with GC. However, for what it's worth, it's not just the absence of garbage collection that makes languages like Rust and C faster. A huge piece of their performance is the level of control that they offer over types' layout in memory and where things get stored. Rust's preference for stack allocations and the absence of a mandatory per-Object size overhead (a la Java) really allow it to shine.


> PHP pages that take two or three full seconds to render

I don't use php personally, but most of my rails apps render full pages in under 100ms. I'd imagine php performance to be at least on-par with a full rails app.


Once you start seeing hundreds or thousands of requests coming in per second and you see your cpu utilization sky rocket, then the "slowness" of the interpreted languages really comes into full play. Most apps/websites will never achieve this kind of load or scale though.


> interpreted languages really comes into full play.

There are plenty of non-interpreted languages that don't require GC though. When you pick Rust you are picking manual memory management. Does even Google opt for non-GCed languages for their web servers?


We've been having a debate lately, within Rust, if "manual" is really the right term here.

  {
      let x = Box::new(5); // malloc

  } // free
Is this really _manual_? In a sense it is, but it's very different than what most people think about. "Automatic" is kind of a good word, but Objective-C/Swift's "ARC" already covers that, and we don't do refcounting, so that could be misleading too.

Maybe "deterministic"?


"RAII" seems to cover it nicely, and extends beyond memory management to other resources. Admittedly it's not a very friendly term for non-C++ programmers.

What's this non-lexical borrowing idea you mentioned in your other comment? (I can't reply there for some reason.) Is there an RFC for that?


The relevant search terms are "SEME regions" and "non-lexical borrows". The tracking issue is here: https://github.com/rust-lang/rfcs/issues/811 and https://github.com/rust-lang/rust/issues/6393 is the older issue it superseded, with examples.

There hasn't been an RFC yet, because we're in the middle of a large amount of compiler internals work (HIR/MIR), which will make overall analysis easier, including these two features.

> (I can't reply there for some reason.)

HN limits responses based on the depth of the comment tree and the length of time since the comment was posted, to discourage flamewars, you can always click on a comment link directly to kind of bypass that though.


Thanks for the issue link (and for the comment-tree depth hint!).


Scope-bound resource management (SBRM) is clearer than RAII, I think.


Memory management in C is also "deterministic", just forget to ever free. :P


How about lexical memory management as a nod to dynamic vs. lexical scoping?


That might work for now, but something we're working on for the future is making borrows non-lexical, so....


Borrows may be non-lexical in the future, but deallocation via ownership will always be at the end of a lexical scope. Not only would eager deallocation be bad for performance, it's also a backcompat hazard at this point.


I personally like:

Rust: "statically memory managed" Java, Go: "dynamically memory managed"

Similar to: "statically typed" or "dynamically typed"


Statically memory managed already has a meaning. It means that there is no malloc during runtime, all memory addresses are decided (usually manually) beforehand and written into the executable.


I wouldn't call it manual at all. It looks remarkably like automatic storage duration IMO.


Google suggests "affine memory management" is not yet used as a term.


I'm thinking Wordpress, or bespoke status pages for internal apps. Of course you can get a PHP page out in under a millisecond if you try hard enough, but it's often not used in that sort of place. (And it often is, but that still doesn't mean it often isn't.)

Rails, for that matter, is known for being easy to produce multi-second pages too.

Slow languages are slow in practice, too.


It actually amazes me that people find the statement that slow languages are actually slow offensive and worthy of downvoting. As I said, it is my experience that simply switching from slow to fast languages even on "IO dominated" workloads has real, visible effects.

If you haven't tried it, consider trying it before becoming offended at the idea that your tool may not be appropriate for all use cases. Yes, it can matter when your language is 50 times slower than another.


I think that line of thinking ends up not applying to rust terribly much.

I know there's been several articles lately about broader applications of rust, and then "is it worth it?" type responses, concerns about "manual memory management", with the implication being there's some heavy tax on not using a GC.

I would certainly agree with the presence of this tax while writing C/C++. (Less with C++, RAII, and especially c++11, but still there.)

With rust, once you're up the learning curve (which, granted, can take a few months), your productivity is not substantially worse than GC'd languages. You pretty much master the borrow checker's semantics, and the best practices to structure things in ways that play nicely with its expectations. And lifetime-related errors don't occupy all that much of your development time.

Source: my team has been re-writing some components of Dropbox's multi-exabyte storage system in rust (from go) over the last 9 months.


That might make you the biggest company using Rust? Very cool, I hope you write it up.


I am fascinated that no one uses Objective C on the back end. Fast, low memory, quick to code in, high-level-enough, a mix of static and dynamic typing, and no garbage collection. Also plenty of expertise you can hire for, maybe already within your company. I think if Obj C had a good story for deploying on Linux (and not losing modern features like ARC), it would make sense to use it, so we'd see sites doing it and open source tools like a good webapp framework. It is because you would need to run OS X servers? (And is that even true?)


I think being so heavily pushed by Apple is actually a downside for ObjC here. I really enjoyed programming ObjC when I was programming for iOS and Mac. That was mostly because of the very rich API shipped with Apple products.

Can you point me to a list of libraries written in ObjC that work without Apple specific code? (E.g. without using anything starting with 'NS')


Gnustep


I'm aware of Gnustep, so I was hoping someone would mention it. But I was hoping for more than one word. How many people are using it in production? Have they had good experiences or bad? What are the surprises they've encountered? Does it have ARC support? Can I use XCode to build with it?


Two big benefits are the static typing and compilation so a I get a lot of benefit from catching errors early, and the second big benefit is static linking.

Other languages give you that ( namely Go ), but I found the correctness checking from rust is _way_ better and I am forced to have much better designs in my programs.

Another Tangential benefit is that I can do lots of great system level things ( High performance data collection, Clustering, Math), and then have a thread pull in a web server and serve out things like statistics and control interfaces.

Also its just nice to program in and the tooling is much nicer then C++


Thanks for your replying. Static typing I won't argue with you, but is static linking important for a web server?

One of the big areas where people choose Go is for cli utilities and static linking is a big reason for that choice. I can see Rust becoming a competitor in this space for the same reason. But for a web server that you control I don't see a huge advantage to static linking.


If I was just working in a SaaS world then maybe static linking isn't a big deal, but I ship and support software across 4 different versions of glibc, libstdc++, and any runtimes for various languages ( Java, python, php, ...). Also I have various versions of MySQL and command line tools. The only things I can guarantee I have are ssh and something that will respond to MySQL connections. In that world being able to push out a single binary and have it just work is priceless.


The one benefit of static linking is reduction of software/library dependencies required for production deployment. In many organizations this means you can develop on any OS/Platform you wish, and then deploy on whatever OS/Platform the ops team is currently running.

Many organizations have yet to adopt devops and templated system deployment methodologies, so it's a legit concern.


> In many organizations this means you can develop on any OS/Platform you wish, and then deploy on whatever OS/Platform the ops team is currently running.

That's true of dynamic linking as well. Static linking just saves you the trouble of having to install the library dependencies on the server. But for ops that's a pretty tiny, if not non-existent gain. So I don't buy it.

When deploying to users it's a huge gain, so I do get that that for things like cli utils.


Depends on your definition of web server, nginx is written in C, even Ruby and Python web servers call to C, they need the performance of C implementations, so I don't see why Rust wouldn't be a good fit for a web server.


Who said Web server doesn't fall into that category? It benefits greatly from better performance.


Ah that's interesting! Can you talk a bit more about the kind of project you're doing ?


My current project is an interface to get detailed application performance statistics off a clustered system. So it connects to a local database and has a configurable list of system checks that it can run. Then it has a defined API that is consumed by the Polymer front end. Rust is nice in that I can do all sorts of great clustering and network programming, and then have a thread that exposes the WebUI and all of that is wrapped up in a single binary. That I can just push to systems and execute.


It would definitely be interesting if you have time to push a sample project somewhere to see how it looks when it's someone that knows what they are doing.


I have some ideas for making hot reload work for web dev i just did not have the time yet :(


What are the compile times like? Is a simple watch script with a re-compile sufficient?


Not the parent, but they've gotten faster every release, so if you've tried Rust in the past, your previous experience would be wrong.

We're in the middle of a big refactoring of the compiler that will eventually enable even more gains. I'm confident rustc will only get faster in the future.


You can't go evangelizing about compile times without even mentioning incremental recompilation. :P

https://github.com/rust-lang/rfcs/pull/1298


Isn't async io pretty much mandatory to compete with the top platforms/frameworks now? I'm certain rust can compete with C++ on raw compute speed, but io is still going to bog it down. Are there any rust frameworks that are using mio yet?


The biggest HTTP library, hyper, has a branch, but will not merge it without mio gaining Windows support. Said support is actively being worked on.


(NB. mio has windows support in master, but it seems that it hasn't been published to crates.io yet.)


Dropbox has something futures-based ala Finagle that's built on mio. We'll be open sourcing it sometime soon-ish.


A Node-style event loop leads to callback hell. It would be awesome to have something like Boost Asio.


Not anymore - with V4 generator based "coroutines" are available (enabled by default).


I was thinking async-await, which I thought hasn't been standardized yet. Do generators provide the same functionality?

Either way, I hope Rust skips the callbacks.


Pretty much, yeah: https://github.com/tj/co


> the server is currently quite slow, only handling around 6.5k req/s for the GET handler, removing the database part makes it shoot up to 70k req/s so something must be going wrong somewhere around postgres

Dynamic typed language frameworks are also around 70k requests per second[1], something must be going wrong outside postgres too.

[1] https://www.techempower.com/benchmarks/#section=data-r10&hw=...


I love this type of exploration and discovery. Sometimes it's the best way to find a diamond in the rough. Who knows? Maybe Rust is the best language for web services, it just needs a little more exploring. Any feedback in terms of RDMS that you can use today or NoSQL? How about reddis? Milliseconds and memory matter when you scale.


Steven Fackler has a fabulous Postgres API at https://crates.io/crates/postgres , MongoDB has an official (though experimental) driver at https://www.mongodb.com/blog/post/the-new-mongodb-rust-drive... , and Armin Ronacher has Redis bindings at https://crates.io/crates/redis (which I can't comment on the quality of, but I assume they're great because Armin (the author of Flask in Python) is a boss at API design).

EDIT: Agh! Armin isn't the author of Requests. :) I'm mad at myself because I even went to the Requests home page to attempt to verify that before posting this comment, and mistook his name under "Testimonials" as an indication of authorship. :P Sorry Kenneth!


Armin isn't the author of requests; that's Kenneth Reitz.


> but I assume they're great because Armin (the author of Flask and Requests in Python)

minor correction, Requests is written by Kenneth Reitz


Minor correction: Kenneth Reitz is the author of Requests.


Postgres and Redis are probably the best two supported datastores. Oh, and Mongo paid some interns this summer to write a new driver as well.


I expect that Rust will actually be really good for the sort of things that Go is currently being used for on the web – i.e. services that don't have user interfaces.

The performance is better and I reckon it's much nicer to write. Unfortunately, the ecosystem isn't there yet.


> The performance is better and I reckon it's much nicer to write. Unfortunately, the ecosystem isn't there yet.

In my preliminary tinkerings, I'm a bit faster writing Go than Rust. I'm not super comfortable with either language. Rust's compiler is a lot more picky, and there's a learning curve to understand how ownership works. Go is a comparatively simple language (which can be a positive or a negative depending on your ideals and usage cases).

I think Go will probably always be "faster" to write, but Rust will keep you from making certain mistakes that you may have sunk debugging time into later. Hard to say where the time break-even is. I am keeping a close eye on both camps so that I'm equipped to make the call as soon as some of our components at work need something faster than Python.


I think one advantage for me that rust has in this area is that you can very easily write core/computational stuff in rust and use it from your current python codebase, and then if/when you need to switch the entire codebase away from python, you've already got the libs done.


If the main goal is static typing, it seems like using a static compile-to-JS language may be better because you can use the whole Node ecosystem. A few choices for static typing (the first two are JS supersets, the second two are just different languages):

* Flow from Facebook

* TypeScript

* Elm

* PureScript


From my experience (used Typescript for a few projects for frontend and tried Flow but ran into bugs/missing things) both TS and Flow type system are easy to fool and in the end you are still writing javascript.

I've never heard of Elm or PureScript being used for backends, users would prefer Haskell I presume. With elm it would require using ports for almost everything, I haven't used PureScript so I can't comment on that.

And as far as ecosystems go, I would prefer using the Python one rather than the Node one.


I just decided to use TypeScript for a new REST API I'm writing. I'd have liked to use Rust instead, but I felt it was still too early (and can't afford the productivity hits of using a new-ish ecosystem).

So far, TypeScript's type system isn't perfect, but it is strict enough to help me catch errors before runtime. Also, there's the (huge) added benefit of making code more readable and self-documenting.

I think I've only had one instance where I violated a type at runtime, but keeping the type system in mind as you're writing your code, you know exactly where those things can or can't happen.

I am really enjoying using Visual Studio's excellent IntelliSense and debugging features, which are on-par with any other web language I've used. Generally speaking, the typing makes hints and autocompletion far better.

Overall, I'd give the whole experience a 7 out of 10. I don't really know of a more productive way to write asynchronous code at the moment.


There are some PureScript projects that I know of running on Node, although it is admittedly less common. I'm currently working on a framework to build REST services in PureScript, so hopefully the situation will improve shortly.


I'd be curious to know how Flow is easy to fool (other than uninitialised class members).


Out of curiosity, how is that better than using Rust? My personal intuition is that by using a compile-to-JS + Node, you lose performance (Node.js is good for I/O, but not great for anything CPU-bound), plus combining Node.js and compile-to-JS is not too easy, if the compiler is not designed specifically for it (typically if it's not CPS-based).

In addition, if you intend to use static typing on generated JS, I suspect that you are going to lose plenty of information.


Are there any good GUI tools for debugging Rust? Python + PyCharm is amazing, except now django.setup() takes so long to run in the debugger, I've switched to print statements.


Any visual tool on top of GDB should work. Microsoft's recent open source efforts mean that Visual Studio debugging is coming along.


I've used Eclipse with the RustDT plugin to debug a project successfully. There's probably ways to make it work in Sublime/Vim/et. al, I just haven't put in the effort to figure it all out yet.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: