The Skylight team, makers of a Rails performance profiler, write about Rust, Ruby integration, and application performance monitoring.
HN commenters mention Skylight as a Rust-in-production example and a Rails monitoring alternative to New Relic, one user citing a year of use.
We've been using Rust in production for Skylight (https://www.skylight.io) for many months now, and we've been very happy with it.
Being one of the first to deploy a new programming language into production is scary, and keeping up with the rapid changes was painful at times, but I'm extremely impressed with the Rust team's dedication to simplifying the language. It's much easier to pick up today than it was 6 months ago.
The biggest win for us is how low-resource the compiled binaries are.
Skylight relies on running an agent that collects performance information from our customers' Rails apps (à la New Relic, if you're more familiar with that). Previously, we wrote the agent in Ruby, because it was interacting with Ruby code and we were familiar with the language.
However, Ruby's memory and CPU performance are not great, especially in long-running processes like ours.
What's awesome about Rust is that it combines low-level performance with high-level memory safety. We end up being able to do many more stack allocations, with less memory fragmentation and more predictable performance, while never having to worry about segfaults.
Put succinctly, we get the memory safety of a GCed language with the performance of a low-level language like C. Given that we need to run inside other people's processes, the combination of these guarantees is extremely powerful.
Because Rust is so low-level, and makes guarantees about how memory is laid out (unlike e.g. Go), we can build…
For what it's worth, I've been using Rust for over a year in my product (http://skylight.io) and it matched my needs pretty closely. Our product is a performance monitoring tool that runs inside of Rails apps, so it's important to us to keep the overhead of our "agent" small and controllable.
Since the agent runs inside of a Ruby program, our only good choices are Ruby itself or a language without a garbage collector (embedding a language with a GC inside a language with GC is asking for trouble -- take a look at the bug tracker for TheRubyRacer for some color). Our initial version of the agent was written in Ruby, but carefully controlling memory usage or performance in Ruby isn't really feasible.
We prototyped a new version of the agent in C++, but I personally didn't feel comfortable shipping a binary that would run in thousands of customers' Rails apps in a language that could segfault if you're not careful. We took Rust very seriously last November, even thought it was still very young, because it gave us a language with direct control over memory with compiler-verified guarantees that our program wouldn't segfault.
TLDR: Rust is a very good choice for writing performance or memory-critical code that will be embedded in a high-level-language.
Also, because it offers compile-time guarantees about safety, I expect it to expand the number of cases where people feel justified in embedding a low-level language for performance-critical problems.
What's going on here is a bit of shorthand. If you don't use the shorthand, the signature looks like:
fn access<'a, T: Send>(guard: &'a mut MutexGuard<T>) -> &'a mut T;
This says that the incoming borrow and the returned borrows have identical scopes (officially called "lifetimes" in Rust; 'a here is a lifetime variable.) It's a very typical pattern: if you return some borrowed data, it generally comes from a borrow you were given, and the shorthand allows you to leave this implicit in cases where it's clear.
EDIT FOR CLARITY: in particular, you're saying that if you take a "sublease" from something you've already borrowed, that sublease is valid for no longer than the original lease. So for example if you borrow a field out of a borrowed structure, the access to the field can last no longer than you had access to the original structure. In this case, we're saying that access to the data lasts no longer than the lock is held.
I'd recommend http://blog.skylight.io/rust-means-never-having-to-close-a-socket/ if you want to get a bit more of a feel for how this works.
The details about the shorthand are here: https://github.com/rust-lang/rfcs/pull/141
Rust's ownership model does more than just allow avoiding a garbage collector.
It allows managing arbitrary resources more easily, so it is clear who is control of things at any point of time, e.g. if a function takes a File, who should close it (if the callee closes it, or if the caller needs to) is just a matter of documentation, while it is expressed naturally in the Rust type signature, and is hence checked by compilers. This isn't unique to Rust, e.g. it's basically the same as C++'s RAII but it is checked far more precisely by the Rust compiler: it is up to the programmer to not make a mistake in C++. http://blog.skylight.io/rust-means-never-having-to-close-a-socket/
It is also an important part about getting guarantees for concurrent code, as it allows fairly precise control over sharing (or not). This not only means Rust code without `unsafe` is free from data races, but also means that, for example, one can be sure a program built on message passing (ala CSP/Go) is not accidentally sharing things that shouldn't be shared. http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html
It's pretty stable at this point (1.x means that no backwards compatibility will be lost as in the past), and it's already used in production (e.g. Skylight [0] is written in Rust, as far as I know, and don't forget about Servo).
Dependency management with Cargo is hands down one of the best out there, it just works. The standard library continues to expand, but there are also many other external libraries you can find on crates.io.
> it looks pretty functional... is it basically a systems-ish scala?
I think it's better to compare Rust to ML languages family (OCaml, F#, and so on), as it was clearly influenced by it. It has many features you can find in ML languages - pattern matching, ADTs (algebraic types that are enums in Rust), and many other similarities.
Overall, the language feels very robust now, and I enjoy it much - it's a very decent replacement for C++, basically "C/C++ done right".
[0] https://www.skylight.io/
> I agree, New Relic's pricing model is almost too "enterprise".
That was also my conclusion, if you look at the list of companies that uses them you will get a list of some very big businesses. And they can probably afford it, which is good for NewRelic.
> I know there's plenty of ways to replicate New Relic, but who has the time?
You could probably use their software, and build a collector for the data, but that doesn't really solve the issue of not building an alternative service.
Yehuda Katz have built Skylight (https://www.skylight.io/) for Ruby performance metrics and they do charge for the number of requests, the platform isn't there yet, but they are improving a lot. Their newsletters are a good read :-)