Live data from Hacker News

Fearless Concurrency in Firefox Quantum

blog.rust-lang.org

81–90 of 177 posts

Re: Fearless Concurrency in Firefox Quantum

#81
post #15

Earlier quoted context omitted.

Note that the panic you get by calling unwrap() where you shouldn't isn't a crash. It's a controlled program exit due to an unexpected condition. While yes, the panic will cause your program to stop, it will do it in a clean deterministic way (with a backtrace). Actual crashes (due to segfaults) can happen a long way from the bug that actually caused the issue, can happen intermittently and generally be a nightmare t…

I think the use of the term "crash" varies. While it's true for e.g. a C program that there are better or worse crashes, in most other modern langs with some more safety guarantees, the term "crash" is normally used for controlled program termination due to unhandled exceptions. So coming from that type of language (where you can't segfault) I'd definitely call a panic a "crash" simply because it's the analog of an u…

It's interesting that the phrase "unhandled exception" has crept so pervasively into our terminology, since "exception" has connotations (e.g. first-class values representing errors, which we can construct, pass around and "throw") and "unhandled" implies that they could be "handled".

Haskell is a great example of how handling errors can be harmful, since it violates confluence, even though throwing errors is fine!

Confluence is the property that evaluation order doesn't change the meaning of a program, e.g. we can do:

    (1 + 2) * (3 + 4)
    3       * (3 + 4)
    3       * 7
    21
Or:

    (1 + 2) * (3 + 4)
    (1 + 2) * 7
    3       * 7
    21
We could inline some function calls if we like, thanks to referential transparency; we can even evaluate "under a lambda" (i.e. evaluate the body of a function before calling it, or evaluating the branches of an `if/then/else` before picking one); regardless of which way we evaluate, if we reach an answer (i.e. don't get stuck in a loop) then it will be the same answer:

    (1 + 2) * (3 + 4)
    (1 + 2) * (if 3 == 0 then 4 else pred 3 + inc 4)
    (1 + 2) * (if 3 == 0 then 4 else pred 3 + 5)
    (1 + 2) * (if 3 == 0 then 4 else 2      + 5)
    (1 + 2) * (if 3 == 0 then 4 else 7)
    (1 + 2) * (if False  then 4 else 7)
    if (1 + 2) == 0 then 0 else (if False then 4 else 7) + (pred (1 + 2) * (if False then 4 else 7))
    if (1 + 2) == 0 then 0 else 7                        + (pred (1 + 2) * (if False then 4 else 7))
    if 3       == 0 then 0 else 7                        + (pred (1 + 2) * (if False then 4 else 7))
    if 3       == 0 then 0 else 7                        + (pred (1 + 2) * 7)
    if False        then 0 else 7                        + (pred (1 + 2) * 7)
    if False        then 0 else 7                        + (pred 3       * 7)
    7                                                    + (pred 3       * 7)
    7                                                    + (2            * 7)
    7                                                    + 14
    21
Exception handlers break this, since we can write expressions like:

    try (head [42, Exception1, Exception2])
    catch Exception1 -> 1
          Exception2 -> 2

We can evaluate this one way:

    try (head [42, throw Exception1, throw Exception2])
    catch Exception1 -> 1
          Exception2 -> 2

    try 42
    catch Exception1 -> 1
          Exception2 -> 2

    42
Or another way:

    try (head [42, throw Exception1, throw Exception2])
    catch Exception1 -> 1
          Exception2 -> 2

    try throw Exception1
    catch Exception1 -> 1
          Exception2 -> 2

    1
Or another way:

    try (head [42, throw Exception1, throw Exception2])
    catch Exception1 -> 1
          Exception2 -> 2

    try throw Exception2
    catch Exception1 -> 1
          Exception2 -> 2

    2
This gives 3 different answers. Note that the throwing itself doesn't cause this problem, because we treat an "unhandled exception" as not getting an answer (equivalent to an infinite loop).

When I first grokked this it was quite enlightening: adding features to a language can make it less useful. It's not that certain features (like throwing or catching exceptions) are "good" or "bad", but that we must think of languages as a whole, and knowing that some things aren't possible (like observing evaluation order) can be just as useful as allowing more things. This contrasts strongly with the tendency of languages to accumulate features over time, especially when the major justification is often "we should have it because they do" :)

There's also a nice discussion on errors vs exceptions at https://wiki.haskell.org/Error_vs._Exception

Re: Fearless Concurrency in Firefox Quantum

#82

Earlier quoted context omitted.

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.

Their devtools have come a long way. And are almost caught up with Chrome. I've only noticed the following things missing: When an XHR response comes back as HTML, there is no "Preview" tab like in Chrome. Also, the responsive testing tool doesn't have the device frames (ie, iPhone, iPad, etc) and it also doesn't have the little touch circle cursor that let's you drag and swipe while testing.

Perhaps you're on an older version of FF, no? Because the things you mentioned are present, just not an exact UI/UX as that with Chrome.

Im on FF Quantum 57.0 (non dev, vanilla FF) and here are my observations:

> When an XHR response comes back as HTML, there is no "Preview" tab like in Chrome.

This is consolidated in the Response tab. You can view it as raw response, or JSON (with filtering options).

> Also, the responsive testing tool doesn't have the device frames (ie, iPhone, iPad, etc)

It does now! You can select and edit a list of device.

> and it also doesn't have the little touch circle cursor that let's you drag and swipe while testing.

They do have a touch simulation mode (pointing hand icon), but it doesnt appear to work at the moment. I cant drag the screen.

Re: Fearless Concurrency in Firefox Quantum

#83
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...

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

Edit: formatting and typo

Re: Fearless Concurrency in Firefox Quantum

#84

Earlier quoted context omitted.

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?)

> Unless you're saying the mutex wraps the vector implying that each vector can have one corresponding mutex at most? The mutex owns the vector. Locking it returns a MutexGuard, which is a smart pointer/reference to the data it owns[0]. You can nest mutexes and structures if you need something slightly more flexible than a single big lock. Having multiple (side-by-side( locks for a single structure sounds like a reci…

> Having multiple (side-by-side( locks for a single structure sounds like a recipe for concurrency bugs & deadlocks.

It is, however, often necessary in order to reduce an undesirable level of contention. For example, hash tables often use fine-grained locking (with one lock per bucket) in order to increase actual parallelism and to prevent the hash table from becoming a serialization bottleneck.

Another common example is the implementation of FIFO queues with two locks (one for the head and one for the tail), which allows threads that read from the queue to avoid/reduce contention with threads that write to the queue.

This is both normal and frequently necessary for performance.

Re: Fearless Concurrency in Firefox Quantum

#85
post #69

Earlier quoted context omitted.

I don't feel this way. What are some neat features of Chrome Dev Tools that I might not be taking advantage of? One I know of is the ability to inspect WebSocket connections, I really wish Firefox had that.

Probably network throttling and responsiveness is the only reason I would switch to chrome for testing. Today is the first day I spent my entire day in Firefox and didn’t get angry. I love it! Ditched chrome for default browser now.

Network throttling is present, but only in responsive design mode. And responsive design mode has the same features with Chrome, but its a bit wonky at the moment.

Re: Fearless Concurrency in Firefox Quantum

#86

Earlier quoted context omitted.

Their devtools have come a long way. And are almost caught up with Chrome. I've only noticed the following things missing: When an XHR response comes back as HTML, there is no "Preview" tab like in Chrome. Also, the responsive testing tool doesn't have the device frames (ie, iPhone, iPad, etc) and it also doesn't have the little touch circle cursor that let's you drag and swipe while testing.

Perhaps you're on an older version of FF, no? Because the things you mentioned are present, just not an exact UI/UX as that with Chrome. Im on FF Quantum 57.0 (non dev, vanilla FF) and here are my observations: > When an XHR response comes back as HTML, there is no "Preview" tab like in Chrome. This is consolidated in the Response tab. You can view it as raw response, or JSON (with filtering options). > Also, the res…

>> When an XHR response comes back as HTML, there is no "Preview" tab like in Chrome.

> This is consolidated in the Response tab. You can view it as raw response, or JSON (with filtering options).

Yeah, I can see the raw HTML or JSON response. But Chrome actually allows you to see the rendered HTML response in the "Preview" tab. Are you saying there is a way to see the rendered HTML from the XHR response? I'm not seeing it. To see the rendered HTML, I have to copy it, create an html file, paste the HTML, then open it in a browser. That's a lot of extra steps when debugging something.

Re: Fearless Concurrency in Firefox Quantum

#88

Earlier quoted context omitted.

Perhaps you're on an older version of FF, no? Because the things you mentioned are present, just not an exact UI/UX as that with Chrome. Im on FF Quantum 57.0 (non dev, vanilla FF) and here are my observations: > When an XHR response comes back as HTML, there is no "Preview" tab like in Chrome. This is consolidated in the Response tab. You can view it as raw response, or JSON (with filtering options). > Also, the res…

>> When an XHR response comes back as HTML, there is no "Preview" tab like in Chrome. > This is consolidated in the Response tab. You can view it as raw response, or JSON (with filtering options). Yeah, I can see the raw HTML or JSON response. But Chrome actually allows you to see the rendered HTML response in the "Preview" tab. Are you saying there is a way to see the rendered HTML from the XHR response? I'm not see…

Oh sorry I misread your comment. Youre right there is no HTML preview indeed

Re: Fearless Concurrency in Firefox Quantum

#89

Earlier quoted context omitted.

> Unless you're saying the mutex wraps the vector implying that each vector can have one corresponding mutex at most? The mutex owns the vector. Locking it returns a MutexGuard, which is a smart pointer/reference to the data it owns[0]. You can nest mutexes and structures if you need something slightly more flexible than a single big lock. Having multiple (side-by-side( locks for a single structure sounds like a reci…

> Having multiple (side-by-side( locks for a single structure sounds like a recipe for concurrency bugs & deadlocks. It is, however, often necessary in order to reduce an undesirable level of contention. For example, hash tables often use fine-grained locking (with one lock per bucket) in order to increase actual parallelism and to prevent the hash table from becoming a serialization bottleneck. Another common exampl…

I think the way that you'd implement the per-bucket locks in a hash table is by having a globally shared (but read-only) vector of buckets, each of which would be a mutex wrapping a vector of key-value pairs. In that way, you don't have multiple locks on the same data structure - you instead have one lock per bucket, which falls back to the simple case described above.

I think an approach similar to this (except with multiple sub-hash-tables, each of which is individually locked) is used by https://github.com/veddan/rust-concurrent-hashmap.

For the two-lock FIFO case, you can definitely do this in Rust but you might need to mark it "unsafe". (I'm happy for someone to prove me wrong on this, though!) "Unsafe" tells Rust "look, I know what I'm doing here" and allows you to do things like operate on raw pointers and generally avoiding checks. However, since Rust is no longer checking these assumptions, you need to be very sure of them yourself!

On the plus side, the rest of your code (e.g. the code using your two-lock FIFO) need not know that an implementation is unsafe - the Rust compiler can still check all the assumptions in that code.

Re: Fearless Concurrency in Firefox Quantum

#90

Earlier quoted context omitted.

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?)

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…

[deleted]
Post reply on HN