Skip to content

libstd’s Duration refactor #18690

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from
Closed

Conversation

1-more
Copy link
Contributor

@1-more 1-more commented Nov 6, 2014

This commit changes the internal representation of Duration from

pub struct Duraion {
    secs: i64,
    nanos: i32
}

to

pub struct Duration {
    millis: i64, // Milliseconds
    nanos:  i32, // Nanoseconds, |nanos| < NANOS_PER_MILLI
}

This commit changes the internal representation of Duration from

    pub struct Duraion {
        secs: i64,
        nanos: i32
    }

to

    pub struct Duration {
        millis: i64, // Milliseconds
        nanos:  i32, // Nanoseconds, |nanos| < NANOS_PER_MILLI
    }
@aturon
Copy link
Member

aturon commented Nov 8, 2014

Thanks for the PR, @1-more! Would you mind outlining the tradeoffs with this new representation and why the choice is being made?

@1-more
Copy link
Contributor Author

1-more commented Nov 9, 2014

That's easy!

Show me your data structures, and I won't usually need your code. This is not the case with the old Duration representation:

  • It has a field named secs, but in code it is restricted to hold values from i64::MIN -1 to i64::MAX milliseconds. Otherwise num_milliseconds() method, which is heavily used throughout Rust's code, overflows.
  • nanos field type is i32, but it is restricted to hold only positive values.

I think that the new representation is more adequate for our purpose:

  • millis field is to hold any i64 value with no num_milliseconds() method overflow.
  • nanos field is to have both positive and negative values.

And last but not least, while our old representation is meant to be compatible with C like Timespec (see this, the new one is easily convertible to that.

@huonw
Copy link
Member

huonw commented Nov 9, 2014

For reviewers, etc: previous discussion.

@1-more
Copy link
Contributor Author

1-more commented Nov 9, 2014

Yeah!

According to previous discussion, the best definition of Duration type should look like:

pub struct Duraion {
    pub ticks: i64, // A single tick represents 100 nanoseconds
}

That is the way .NET and Joda-Time go. It gives the best performance. It fits to alignment rules. The full range of values is large enough etc. But it takes nanoseconds away.

Nobody knows do we really need them. At the moment, the only place in Rust code that uses Duration::nanoseconds and Duration::num_nanoseconds() is this file. It also the only one that uses C like Timespec.

The discussion is still in progress. My commit respects Timespec and nanos, but makes the Duration type a bit more consistent.

/// An absolute amount of time, independent of time zones and calendars with nanosecond precision.
/// A duration can express the positive or negative difference between two instants in time
/// according to a particular clock.
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord, Zero, Default, Hash, Rand)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This derived Rand is incorrect: an arbitrary random i32 x is highly likely to have |x| >= NANOS_PER_MILLI violating the restriction on nanos.

}

/// Returns the total number of whole microseconds in the duration,
/// or `None` on overflow (exceeding 2^63 microseconds in either direction).
/// Returns the total number of microseconds in the duration.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can still overflow, so the mention of when None is returned should be maintained/updated.

@huonw
Copy link
Member

huonw commented Nov 9, 2014

Hm, could you explain why the change made here is neither of the suggestions from the previous discussion?

At the moment, the only place in Rust code that uses Duration::nanoseconds and Duration::num_nanoseconds() is this file

The stdlib/compiler is not a particularly good place to look for uses of specific functions. This repo will not care or need many functions: they are mainly designed for use by others. A global search of github is a slightly better way to measure the prevalence of a function.

@huonw
Copy link
Member

huonw commented Nov 9, 2014

(To be clear, I don't necessarily think this design is bad, it was just a little surprising to me to follow that discussion and then see something else implemented, so a bit of background motivation for the change would be nice.)

@1-more
Copy link
Contributor Author

1-more commented Nov 9, 2014

Well, as I've said before: the discussion is still in progress. And at least one file exists that needs Duration::nanoseconds and Duration::num_nanoseconds(). I don't want to break someone else's code ...

As for is_digit method includes non-ASCII digit sequences, I have no idea at the moment. Any advice?

@huonw
Copy link
Member

huonw commented Nov 9, 2014

Well, as I've said before: the discussion is still in progress

Sure, the discussion is in progress, but this PR seems to be ignoring that discussion entirely. I don't think the choice here is bad, per se, but I would like to see some justification for it, i.e. why we should change Duration to this format rather than leaving it as is or changing it to one of the proposals in the discuss thread (since apparently they are the best format).

(I see you've justified why we shouldn't leave it as-is above, but the latter is still missing: why is ticks: i64, nanos: i8 less appropriate?)

As for is_digit method includes non-ASCII digit sequences, I have no idea at the moment. Any advice?

Just do normal comparison: '0' <= c && c <= '9'.

@1-more
Copy link
Contributor Author

1-more commented Nov 9, 2014

ticks: i64, nanos: i8 vs millis: i64, nanos: i32?

There is no big difference between them. It's 3 bytes less vs 3 bytes more choice, that is nothing due to alignment rules. But in second case the full range of values is larger. It might be important for someone.

In fact, I dislike both and wish the third case (ticks: i64) to be.

@1-more
Copy link
Contributor Author

1-more commented Nov 10, 2014

I found one more reason why ticks: i64, nanos: i8 (or even ticks: i64) is less appropriate:
num_microseconds method will always return a valid i64 value. I mean we should change method signature from:

pub fn num_microseconds(&self) -> Option<i64>

to

pub fn num_microseconds(&self) -> i64

But it might to be a compatibility issue. Or leave it as is, then it'll be inconsistent.

@1-more 1-more closed this Nov 16, 2014
lnicola pushed a commit to lnicola/rust that referenced this pull request Dec 23, 2024
…string

feat: Use string literal contents as a name when extracting into variable
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants