
Fearless Concurrency in Firefox Quantum - ahomescu1
https://blog.rust-lang.org/2017/11/14/Fearless-Concurrency-In-Firefox-Quantum.html
======
kibwen
I like this explanatory comment by Manishearth, a Servo dev, in the thread
over on /r/rust:

 _" This blog post brought to you by the 'how many times can you say 'fearless
concurrency' and keep a straight face' cabal.

"Seriously though, I now appreciate that term a lot more. One thing that
cropped up in the review of this post was that I didn't have examples of bugs
Rust prevented. Because I couldn't think of any concrete ones. Because Rust's
safety doesn't work that way, it prevents your concurrency bugs before you
realize you had them, by making sure you don't paint yourself into a corner.
'Fearless concurrency' really is the best way of putting this; the benefit was
not that it prevented concrete bugs, but that it let us fearlessly and
aggressively write code knowing that it would be concurrency bug free."_

[https://www.reddit.com/r/rust/comments/7cwpbq/fearless_concu...](https://www.reddit.com/r/rust/comments/7cwpbq/fearless_concurrency_in_firefox_quantum/)

~~~
ekidd
I've spent the last few days aggressively parallelizing some Rust code with
crossbeam, and it's really just... painless (once you're used to Rust). Rust
actually understands data races, and it grumbles at me until my code is
_provably_ safe, and then everything Just Works.

The Rayon library is also lovely for data parallelism.

Sometimes, I think, "Rust is basically a nicer C++ with the obvious foot guns
removed and great tooling", but then there are those moments where I'm just
blown away by what a good job it does.

(I think it helps that I have some functional programming experience under my
belt, and that I tend to use mutability sparingly, and mostly in very simple
ways.)

~~~
StavrosK
> painless (once you're used to Rust)

This needs to be Rust's motto or something.

~~~
naasking
> This needs to be Rust's motto or something.

Rust: climb that mountain so you can see further.

~~~
forgot-my-pw
Rust: it's relatively easy when you're an expert!

~~~
StavrosK
Rust: Expected String, got str.

------
pornel
Rayon is pretty cool. It's about as powerful as OpenMP, and a bit easier to
use.

The fearless concurrency really is ass-saving. For example, my most recent
non-bug: I launched two parallel tasks where one would free a shared resource
when done. In C that would be intermittent use-after-free. In Rust it was a
compile-time error.

------
tareqak
Congratulations to the Mozilla and Rust teams!

Accounts like this one really help people who advocate investing in and
building new tools to help against the heavy-handed application of phrases
like "a bad workman always blames his tools" [0][1].

[0]
[https://en.wiktionary.org/wiki/a_bad_workman_always_blames_h...](https://en.wiktionary.org/wiki/a_bad_workman_always_blames_his_tools)

[1]
[https://en.oxforddictionaries.com/definition/a_bad_workman_a...](https://en.oxforddictionaries.com/definition/a_bad_workman_always_blames_his_tools)

Edit: formatting and typo

~~~
Analemma_
I hate that phrase and its reflexive usage so much. Yes, a bad workman blames
his tools, but so does a good workman using lousy tools.

~~~
chowells
You can respond with "that's because a good workman doesn't use poor tools."

It nicely suggests that maybe it's the programmer's responsibility to advocate
for something better.

~~~
nitrogen
When I was a kid I used to pride myself on how many things I could take apart
and reassemble with just a butter knife. But that was only because I didn't
have access to real screwdrivers.

Likewise with software, each improved tool I learn (or new but worse tool I
learn to avoid) makes me appreciate how much time I could have been wasting by
using inferior tools/practices/languages.

------
vatotemking
Firefox Quantum is blazing fast, and I finally ditched Chrome.

My only problem is that it drains my battery life fast. So whenever I'm not
plugged I use Edge. Other than that, FF is amazing.

It is now my default browser and I even wrote a FF add-on a few days ago using
their new API!

~~~
Zenbit_UX
As a front end Dev I'll never fully ditch Chrome as its Dev tools are vastly
superior. I've tried the Firefox inspect menu and I'm just immediately turned
off and confused..

However Firefox has been, and always will be my daily driver for all Web
browsing. It's eco system is richer, noscript and the fact that it's not a
Google product is a huge selling point.

~~~
nwah1
From a feature standpoint, I can't think of anything that Firefox devtools are
lacking. This seems like a gripe about the UI, and my feeling is precisely the
opposite of yours, but equally subjective.

~~~
benjvmin
Just testing out FF devtools, I do appreciate how similar they are to Chrome.
The biggest differences seem to be geared towards PWAs, such as auditing w/
Lighthouse.

------
margorczynski
From the article it seems Rust is really a great replacement for C++ and all
it's complexity and quirks. I wonder how many other C++ projects are
considering moving to it, anyone know about any major one like FF?

~~~
simias
I'm a former C++ dev who went all in on Rust. I think the main problem is that
the learning curve works in Rust's disadvantage here.

If you start learning C++ it's relatively smooth sailing at first, especially
if you're already familiar with C. Basic OOP, basic RAII, inheritance, virtual
functions, basic templates. Easy peasy.

It's once you start getting to the advanced topics that the footguns become
apparent. The sometimes intricate resolution rules (and how they compound with
template substitution rules), the various subtleties surrounding copy
constructors, const, mutable, concurrency and the way they play with each
others, the various quirks inherited from C that sometimes don't play very
well with modern constructs etc...

Rust is the other way around. There's a very steep curve right at the start
where you need to understand how the borrow checker works and how to make it
happy. You have to learn the right mindset right away. You need to get over
that to reach the "fearless confidence" goodness.

I think that's going to be a big problem for experienced C++ coders to do the
jump (especially if you need to convince multiple devs to make the jump at the
same time).

It kind of reminds me of the switch from SVN to git. At first I didn't get it,
git felt a lot more complicated and I didn't really see the benefit compared
to good old SVN. Of course after a few years I'd curse under my breath every
time I had to use SVN for some legacy codebase, it feels so clunky and limited
now that I'm familiar with a proper git workflow.

~~~
adrianN
Already basic C contains more than enough footguns. If you think basic C++ is
relatively free of footguns you're kidding yourself. Rust has a steep learning
curve because the compiler nags you a lot about things that would have been a
potential footgun in C. Unfortunately it is not smart enough to see in all
cases that your code wouldn't have triggered that particular footgun and has
to be overly conservative.

~~~
simias
I meant that basic C++ seems rather straightforward and at first doesn't
appear to introduce too many new footguns over the C subset. Actually thanks
to vectors and RAII it can remove whole classes of classic C mistakes.

It's only when you start to have all these elements work (or not work)
together that you realize that it's not as simple as it first seemed and the
various side effects, overloadings and implied constraints sprinkled
throughout the code turned it into a virtual minefield.

Case in point, this video I've watched the past week:
[https://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-
Sutte...](https://channel9.msdn.com/posts/C-and-Beyond-2012-Herb-Sutter-You-
dont-know-blank-and-blank)

It's a very interesting talk (and probably worth a watch if you're a C++
developer) but the amusing thing to me is that he begins by showing two short
pieces of rather simple C++ code and asks the audience if they are UB or not.
Seems like nobody can (or want to) answer that question.

Spoiler: the conclusion of the talk is that one of these pieces of code is
only legal if the copy constructor of the custom type adheres to certain
implied constraints that are not enforced by the compiler and, it seems, few
people are aware of.

------
throwaway613834
Could someone give a very simple, to-the-point example of a kind of
concurrency bug that Rust prevents, for those of us who don't know Rust? (The
author explicitly fails to think of any, so I'm hoping someone else can. It'd
be more convincing to see one.)

EDIT: I meant a code example, not a paragraph. And I would obviously expect to
see how the intended goal is achieved _without_ the bug... otherwise it'd be
trivial to prevent any bug (just make everything impossible).

~~~
maffydub
Borrowing from [https://blog.rust-lang.org/2015/04/10/Fearless-
Concurrency.h...](https://blog.rust-lang.org/2015/04/10/Fearless-
Concurrency.html) (linked to from the original post), the following code tries
to access a lock-protected vector.

    
    
        fn use_lock(mutex: &Mutex<Vec<i32>>) {
            let vec = {
                // acquire the lock
                let mut guard = lock(mutex);
        
                // attempt to return a borrow of the data
                access(&mut guard)
        
                // guard is destroyed here, releasing the lock
            };
        
            // attempt to access the data outside of the lock.
            vec.push(3);
        }
    

It doesn't compile because the lock is not held long enough.

    
    
        error: `guard` does not live long enough
        access(&mut guard)
                    ^~~~~
    

There are several more examples in that article, but you can read them there
rather than here!

~~~
throwaway613834
Thanks (upvoted)! However how in the world would the compiler know if the
mutex belongs to the same vector you are accessing? (Unless you're saying the
mutex wraps the vector implying that each vector can have one corresponding
mutex at most? Which seems quite limiting?)

~~~
maffydub
Thanks!

Yes, when you construct a mutex, you give it ownership of the vector you want
it to protect. Due to the way Rust works, once you've given ownership to
something else, you can no longer access it yourself.

The only way you can get access to the data again is to "borrow" a reference
to it, but this borrow has a "lifetime", which is tied to the period for which
you're holding the mutex. This is how the compiler can spot that you've tried
to access the vector after the mutex has been released.

As you say, this means that each vector can only have one mutex wrapping it -
at least for this implementation of mutex, known as std::sync::Mutex (
[https://doc.rust-lang.org/std/sync/struct.Mutex.html](https://doc.rust-
lang.org/std/sync/struct.Mutex.html)).

However, if you're looking for something like a read/write lock, Rust supports
that too via std::sync::RwLock - see [https://doc.rust-
lang.org/std/sync/struct.RwLock.html](https://doc.rust-
lang.org/std/sync/struct.RwLock.html) for more details.

Obviously, the example uses a vector, but Rust has a pretty strong system of
generics, so your mutex (or read/write lock) can wrap pretty much any type,
e.g. a struct you've defined.

Hope that makes sense - this was one of the areas of Rust that impressed me
most!

~~~
throwaway613834
Yeah that makes sense! It strikes me as pretty similar to volatile-correctness
in C++ (it's a technique -- look it up if you haven't heard of it) with the
additional constraint that there is only ever one mutable reference, for
better or for worse.

~~~
Rusky
For cases where you need more than one mutable reference, you can use `Cell`
(single-threaded) or atomics, which allow mutation through shared references.

------
ape4
The new Firefox is actually faster.

~~~
MaxBarraclough
My only complaint is the marketing.

Firefox isn't slow, sure enough. But it wasn't slow last week either. I've
been using it as my primary browser for a long time, and performance was never
an issue.

Also, 'Quantum'? Come on now. If they're aiming Firefox at power-users (which
they should be), they should know that kind of buzzword abuse is only going to
annoy.

~~~
asadjb
Anecdotal evidence, so take it with a grain of salt.

I switched to Firefox 2 days ago, after reading a post about how Firefox has
recently got faster. I have been a Chrome user for more than a couple of years
now, when I switched from Firefox because it was _slow_ in comparison.

After using Firefox for 1 day, it already seemed slower than what I was used
to in Chrome. This was most noticeable on ad-laden sites that displayed video
ads or similar. I hadn't installed ad-blockers I had on Chrome yet, so maybe
it was just that.

After 1 day of use, I was ready to switch back. But then I installed Quantam
yesterday, and boy has it been amazing! It is noticeably faster, without any
ad-blockers or extensions.

So atleast for me, it was slower last week, and just got fast.

~~~
nikbackm
Why did you switch 2 days ago instead of waiting for 57?

Just a co-incidence?

~~~
asadjb
Yes. :)

------
nobodyorother
My kingdom for Tab Groups! [https://addons.mozilla.org/en-
US/firefox/addon/tab-groups-pa...](https://addons.mozilla.org/en-
US/firefox/addon/tab-groups-panorama/)

------
faragon
Any side effects on web applications? E.g. event handling race conditions or
different behavior?

------
jsf666
> It replaces approximately 160,000 lines of C++ with 85,000 lines of Rust

Wow! This is great, especially considering how bad and complex (in the bad
sense) C++ is. Maybe Rust and Go will finally make the Frankenstein go to
sleep

~~~
zellyn
Is this reduction in line count typical? I'm surprised. Or is this discounting
parts of the code that have been moved out into separate crates?

~~~
Rusky
There's some good discussion of how it happened here:
[https://www.reddit.com/r/rust/comments/7cwpbq/fearless_concu...](https://www.reddit.com/r/rust/comments/7cwpbq/fearless_concurrency_in_firefox_quantum/dpt9gq0/)

One of the biggest contributors is "custom derive," which cuts out a lot of
boilerplate. Another is that Gecko C++ is also pretty old and so doesn't rely
on a lot of what is now standard. It's also just a ground-up rewrite, which
has the advantage of hindsight.

It's not a trick of moving code around.

~~~
zellyn
Oh, thanks. Perfect link. It makes sense that rewrites are smaller, but the
reduction factor was still surprising.

------
mangatmodi
Is it a concern that acid3 test as terribly faild? -
[http://acid3.acidtests.org/](http://acid3.acidtests.org/)

~~~
24gttghh
I'm sorry? I just scored a 97/100 using FF v57.0 x64. That's decent right? The
newest version of Chrome fails likewise.

Also this:

>Acid3, in particular, contains some controversial tests and no longer
reflects the consensus of the Web standards it purports to test, especially
when it comes to issues affecting mobile browsers. The tests remain available
for historical purposes and for use by browser vendors. It would be
inappropriate, however, to use them as part of a certification process,
especially for mobile browsers.[0]

[0][http://www.acidtests.org/](http://www.acidtests.org/)

------
wahern
Fearless, indeed:
[https://github.com/servo/servo/issues?page=1&q=thread+race](https://github.com/servo/servo/issues?page=1&q=thread+race)

~~~
Argorak
Rust only saves you from simple races, not more complex ones. That's quite a
lot already.

Most importantly, though, it preserves _memory safety_ in concurrent
situations, so your stuff won't randomly crash, but properly panic.

It's no silver bullet, but it _is_ the "magic sauce" behind Stylo.

~~~
deckarep
I’m pretty sure Rust saves you from ALL data races so long as you stay within
the boundaries of safe code. Do you have anything at all to reference
otherwise that says only certain data races are detected while others are not?

To my knowledge you can defeat the compile-time data race detection if you are
either doing unsafe or certain scenarios with Cell/RefCell but even in that
case you are guaranteed runtime detection rather than compile time detection.

These feature alone is worth its weight in gold.

~~~
s17n
Given the a "data race" is essentially defined to be the class of races that
Rust's type system guards again, yeah it saves you from all of them.

~~~
kibwen
Rust's definition of "data race" isn't just "what the Rust compiler rejects",
it has a specific meaning:

 _" Safe Rust guarantees an absence of data races, which are defined as: 1.
two or more threads concurrently accessing a location of memory, 2. one of
them is a write, 3. one of them is unsynchronized."_

[https://doc.rust-lang.org/nomicon/races.html](https://doc.rust-
lang.org/nomicon/races.html)

