Live data from Hacker News

Announcing Rust 1.27

blog.rust-lang.org

11–20 of 80 posts

Re: Announcing Rust 1.27

#11
post #4

The new syntax for dynamically-dispatched traits, “dyn Trait”, is an example of Rust’s persistently excellent consideration of what should be explicit and what should be implicit. Python’s mantra of “explicit is better than Implicit” mostly captures my general feeling, but you can’t make everything explicit. Back before impl Trait existed, just Box seemed very clear. Now that there’s an important thing to differentia…

> Rust’s trait object syntax is one that we ultimately regret. Would someone please explain the problem (and the solution) for someone who doesn't know Rust yet?

A trait is like an interface. A struct implementing a trait means it takes on the methods of that interface (but there's more to it, because a trait can have default implementations of of the trait methods).

If you want to express something like "this is a variable that holds something that fulfils this trait", without knowing the _actual_ type it is, that variable effectively has an unknown runtime size. std::io::Read is an interface for reading bytes of some source, like a file or a socket.

This matters because we're talking about a stack frame. So the size needs to be known at compile time.

    let a: u64 = 42; // ok, because well known size.

    let b: Read = ...; // illegal, because unknown size.
A "trait object" places the object on the heap and has a pointer in its place.

    let b: Box = ... // legal, because pointer is a known size
However it's a bit more complicated, because this syntax allows for dynamic dispatch at runtime using a vtable. So there's a quite big difference between Box (a 64 bit unsigned integer on the heap) vs Box (a runtime dispatched lookup via a vtable).

This difference is not obvious at a glance though. Hence the new syntax: Box.

(I think I got that right)

Re: Announcing Rust 1.27

#12
post #4

Earlier quoted context omitted.

> Rust’s trait object syntax is one that we ultimately regret. Would someone please explain the problem (and the solution) for someone who doesn't know Rust yet?

A trait is like an interface. A struct implementing a trait means it takes on the methods of that interface (but there's more to it, because a trait can have default implementations of of the trait methods). If you want to express something like "this is a variable that holds something that fulfils this trait", without knowing the _actual_ type it is, that variable effectively has an unknown runtime size. std::io::Re…

You did, except that it’s not one pointer, it’s two. This is one way that rust is different than C++; the vtable isn’t stored with the data, but separately, with the “trait object” itself being two pointers to the two things.

Re: Announcing Rust 1.27

#13

Earlier quoted context omitted.

A trait is like an interface. A struct implementing a trait means it takes on the methods of that interface (but there's more to it, because a trait can have default implementations of of the trait methods). If you want to express something like "this is a variable that holds something that fulfils this trait", without knowing the _actual_ type it is, that variable effectively has an unknown runtime size. std::io::Re…

You did, except that it’s not one pointer, it’s two. This is one way that rust is different than C++; the vtable isn’t stored with the data, but separately, with the “trait object” itself being two pointers to the two things.

Good to know!

Re: Announcing Rust 1.27

#14

SIMD on stable is very exciting news. SIMD unlocks the power of the GPU-esque parallelism that is already inside your CPU. While compilers do try very hard to take advantage of this automatically, it’s not always predictable and can make performance fragile. This is what people are talking about when they refer to “low level control”. Don’t expect that with Rust 1.27 you’ll need to understand SIMD to get anything don…

How useful is SIMD on CPU these days given that most of the touted original applications (back in the MMX SSE days) have been moved over to GPUs?

GPUs are sadly not generally usable yet.

Re: Announcing Rust 1.27

#15

SIMD on stable is very exciting news. SIMD unlocks the power of the GPU-esque parallelism that is already inside your CPU. While compilers do try very hard to take advantage of this automatically, it’s not always predictable and can make performance fragile. This is what people are talking about when they refer to “low level control”. Don’t expect that with Rust 1.27 you’ll need to understand SIMD to get anything don…

How useful is SIMD on CPU these days given that most of the touted original applications (back in the MMX SSE days) have been moved over to GPUs?

Very useful. SIMD has a much lower barrier to use (doesn't need graphics drivers, GPGPU frameworks etc., almost universally available and fallbacks are easily implemented) and is much easier to target (same language, same toolchain, same memory model).

Also notice that the execution model of GPUs and CPUs is quite different. You need a far larger "breadth" of execution to efficiently use a GPU, compared to a CPU.

Re: Announcing Rust 1.27

#17

SIMD on stable is very exciting news. SIMD unlocks the power of the GPU-esque parallelism that is already inside your CPU. While compilers do try very hard to take advantage of this automatically, it’s not always predictable and can make performance fragile. This is what people are talking about when they refer to “low level control”. Don’t expect that with Rust 1.27 you’ll need to understand SIMD to get anything don…

How useful is SIMD on CPU these days given that most of the touted original applications (back in the MMX SSE days) have been moved over to GPUs?

Stuff like compression algorithms, some codecs (not all use GPU), some high-performance parsers, some encryption stuff (e.g. openssl), some databases (often column stores, also redis I think), language VMs etc use SIMD.

More generally SIMD is useful when you are repetitively performing the same instruction on a long stream of data but you don't want to send it over to the GPU because you don't want to incur the many order of magnitude slowdown of sending stuff back and forth to another chip or you can't rely on a GPU being there (e.g. embedded), or it's just overkill.

Re: Announcing Rust 1.27

#18
post #4

The new syntax for dynamically-dispatched traits, “dyn Trait”, is an example of Rust’s persistently excellent consideration of what should be explicit and what should be implicit. Python’s mantra of “explicit is better than Implicit” mostly captures my general feeling, but you can’t make everything explicit. Back before impl Trait existed, just Box seemed very clear. Now that there’s an important thing to differentia…

> Rust’s trait object syntax is one that we ultimately regret. Would someone please explain the problem (and the solution) for someone who doesn't know Rust yet?

Reading up an static vs dynamic dispatch may help - https://en.wikipedia.org/wiki/Dynamic_dispatch.

Essentially Box is static dispatch. You know at compile time which exact methods you are going to call. Box is dynamic dispatch. Since Foo is a trait, at compile time you won't know which methods are called, it depends on the type of the object passed in (as long is it implements the Foo trait).

Re: Announcing Rust 1.27

#19
post #5

Yes!! I have been waiting for the new time helpers to arrive in stable. It may be a small thing but is so much nicer and makes Rust feel more like a higher level language when I can do `some_time.subsec_millis()` rather than `some_time.subsec_nanos() / 1_000_000`.

I don't understand your comment. It feels like a higher level language because you can use a different unit for measuring time?

Re: Announcing Rust 1.27

#20
post #19
post #5

Yes!! I have been waiting for the new time helpers to arrive in stable. It may be a small thing but is so much nicer and makes Rust feel more like a higher level language when I can do `some_time.subsec_millis()` rather than `some_time.subsec_nanos() / 1_000_000`.

I don't understand your comment. It feels like a higher level language because you can use a different unit for measuring time?

Having written enough of boilerplate to do millisecond timestamps, or including a quite big chrono library for a nicer interface for a few time operations, these additions are quite luxurious.
Post reply on HN