|
|
Subscribe / Log in / New account

Rust 1.60.0 released

Version 1.60.0 of the Rust language is available. Changes include coverage-testing improvements, the return of incremental compilation, and changes to the Instant type:

Prior to 1.60, the monotonicity guarantees were provided through mutexes or atomics in std, which can introduce large performance overheads to Instant::now(). Additionally, the panicking behavior meant that Rust software could panic in a subset of environments, which was largely undesirable, as the authors of that software may not be able to fix or upgrade the operating system, hardware, or virtualization system they are running on.


to post comments

Rust 1.60.0 released

Posted Apr 7, 2022 20:50 UTC (Thu) by tialaramex (subscriber, #21167) [Link]

The change to Instant monotonicity promises were the right highlight for LWN because if there are people who see this problem they're probably LWN readers (I think I've read pieces about trying to make Linux guarantee this here). However if you have the comfort of writing software in a less fraught environment which doesn't experience time travel, there are two nice small safety improvements in the library here I think are worth a moment.

5.abs_diff(-10) == 15 means you can ask "These two (maybe signed) integers I have, how big is the difference between them?" and get an (unsigned) answer without spending ten minutes trying to figure out if your solution does anything unexpected in corner cases each time or worrying whether you're doing something needlessly slow.

Wrapping<T> getting OpAssign<T> implementations means e.g. Wrapping<i8> (a signed 8-bit integer which exhibits wrapping behaviour on overflow) has operators like += and *= working on i8 operands. So now:

let acc: Wrapping<i8> = 0;
let a: i8 = blackbox_100();
acc += a;
let b: i8 = blackbox_100();
acc += b;

... is a nice, syntax light way to express the fact you want the hardware two's complement behaviour for your accumulator acc, and you won't be surprised that acc is now -56 because that's how wrapping arithmetic works.

Rust's i8 will actually do this in release builds by default 'cos it's fast, but because overflow usually represents a programming error it will panic in debug builds when the overflow occurs, so Wrapping<i8> is the way to express that you deliberately want wrapping arithmetic and now it has a nicer affordance for this type of accumulation operation.

Rust 1.60.0 released

Posted Apr 8, 2022 1:43 UTC (Fri) by jkingweb (subscriber, #113039) [Link] (7 responses)

> To work around these bugs and platforms not offering monotonic clocks, Instant::duration_since, Instant::elapsed and Instant::sub now saturate to zero.

Pardon my ignorance. What does "saturate to zero" mean?

Rust 1.60.0 released

Posted Apr 8, 2022 3:37 UTC (Fri) by nybble41 (subscriber, #55106) [Link] (4 responses)

> What does "saturate to zero" mean?

If the difference would be negative (an earlier time minus a later time) it's replaced with zero.

Rust 1.60.0 released

Posted Apr 8, 2022 14:40 UTC (Fri) by tialaramex (subscriber, #21167) [Link] (3 responses)

The consequences of this being, AIUI:

* If your environment / OS / hardware is broken and insists that some First Thing happened after a Second Thing, Rust will tell you that time somehow stood still rather than going backwards, on the assumption that your program is much more likely to do something correct if time stood still than if time went backwards. Previously Rust might panic because this should be impossible (but it wasn't)

* If you screwed up and ask Rust for the wrong order of events now Rust says zero, rather than panicking. As a result you might miss bugs in your logic which would previously panic and highlight themselves. This is why Rust reserves the right to come back later and have this case panic again, if (chance would be a fine thing) hardware and VMs both learn not to do time travel. If you start doing this on purpose you are Doing It Wrong™

* If you are trying to add together intervals to attempt some sort of dead reckoning of time, now Rust says this won't panic if things go wrong, but your results may be wrong still so it's probably a bad idea and you should ask for the actual time, which is unlikely to be any less reliable than these wonky interval timers.

* If your hardware/ OS/ environment all work perfectly and your program is correct, it should now also perform as expected with regard to interval timers, instead of being mysteriously slow (as Rust tries to compensate for broken hardware/ OS/ environments)

* If you need a reliable interval timer, but the one documented for your hardware is broken, Rust takes no responsibility for that, try bugging the hardware vendor (ha) or build your own.

Rust 1.60.0 released

Posted Apr 10, 2022 20:25 UTC (Sun) by NYKevin (subscriber, #129325) [Link] (2 responses)

Bonus bullet point:

* If you *don't* use leap smearing, and a leap second happens, then time will appear to stand still rather than going backwards (which is what officially happens under Unix time). Since there's no good way to fix this other than leap smearing, and leap smearing is a system-wide or even cluster/DC-wide change which Rust is not in a good position to enforce, the consequence of this is that any program written in Rust must be able to tolerate time standing still for 1 second every now and then, even if it is not intended to run on broken hardware.

Rust 1.60.0 released

Posted Apr 10, 2022 21:35 UTC (Sun) by atnot (subscriber, #124910) [Link]

This is not true, time::Instant uses monotonic clock sources (e.g. clock_gettime(CLOCK_MONOTONIC) on unix) which are not affected by leap seconds.

Rust 1.60.0 released

Posted Apr 10, 2022 22:17 UTC (Sun) by excors (subscriber, #95769) [Link]

I thought the alternative to leap smearing/slewing was that the clock would jump back by 1 second from approximately 00:00:00.000 to 23:59:59.000 (as described in https://lwn.net/Articles/648313/)? That would only appear to stand still if you're looking at 1-second-precision timestamps from a UTC-based clock (e.g. time()), and in that case you'll already be used to it standing still for billions of CPU cycles, so a few billion more shouldn't matter. If you're using a higher-precision UTC-based clock (e.g. gettimeofday()) then you'll see it go backwards, which may be surprising (and is a reason to avoid using such clocks where possible).

If you're using a high-precision monotonic non-UTC clock (e.g. clock_gettime(CLOCK_MONOTONIC), or QueryPerformanceCounter on Windows) then it'll ignore the 1-second jump entirely and keep counting as normal. That's the relevant case for Rust's std::time::Instant which is meant for measuring high-precision durations and has no meaningful epoch.

Rust 1.60.0 released

Posted Apr 9, 2022 4:02 UTC (Sat) by ncm (guest, #165) [Link] (1 responses)

A better way to express it would be "clip to non-negative".

Rust 1.60.0 released

Posted Apr 13, 2022 15:04 UTC (Wed) by starblue (guest, #5842) [Link]

This terminology is not new.

There are already arithmetic operations called `saturating_*` on integer types that saturate to maximal values on overflow and minimal on underflow. So unsigned types saturate to zero when the true result would be negative. The same now applies to the duration resulting from the subtraction of two instants.


Copyright © 2022, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds