Skip to main content

Frequency

Struct Frequency 

Source
pub struct Frequency { /* private fields */ }
Expand description

How often a block runs, relative to one entry to the function it is in.

The entry block is Frequency::ENTRY, which is one. A block inside a loop predicted to run ten times is ten. A block on an error path is a fraction. The unit is deliberately relative: how often this block runs compared to the whole function is a question that can be answered without a profile, and how often it runs compared to the rest of the program cannot.

Implementations§

Source§

impl Frequency

Source

pub const ENTRY: Self

One execution per entry to the function, which is what the entry block gets.

Precise, because it is not a claim about the program. It is the definition of the unit.

Source

pub const NEVER: Self

The block does not run at all.

Source

pub const UNKNOWN: Self

Nobody has computed one for this block yet.

Zero, so that a consumer that ignores the quality is at least conservative rather than wrong in the direction that puts cold code in the hot section. The quality is what says the zero means nothing.

Source

pub const MAX: Self

As high as this goes, which is what everything saturates to.

A frequency here means the arithmetic ran out of room, which nested loops will do to any fixed size number. What it must not do is wrap, because a hot block that comes out cold is a decision nobody can explain afterwards.

Source

pub const fn times(count: u32, quality: Quality) -> Self

Runs this many times per entry to the function, believed this much.

Source

pub const fn raw(self) -> u64

The raw fixed point value, scaled by Probability::SCALE.

For a dump or a comparison. A consumer doing arithmetic on this rather than on the Frequency is a consumer that has dropped the quality on the floor.

Source

pub const fn quality(self) -> Quality

How much this is worth believing.

Source

pub const fn is_saturated(self) -> bool

Whether the arithmetic ran out of room getting here.

Source

pub fn along(self, edge: Probability) -> Self

This block’s frequency carried along an edge taken this often.

Source

pub fn plus(self, other: Self) -> Self

Two paths into the same block.

Source

pub fn repeated(self, iterations: u32) -> Self

This block, once per iteration of a loop that runs iterations times.

The caller clamps the iteration count before it gets here, per section 11.2. Saturating multiplication keeps the arithmetic honest, but a nest of loops each claimed to run four billion times has already lost the argument somewhere further up.

Source

pub fn repeated_while(self, again: Probability, cap: u32) -> Self

This block’s frequency once the loop it heads has gone round as often as it is going to.

The header of a loop runs once for the iteration that enters it and again for every iteration that goes back to it, so if again is the probability of going round, the header runs 1 / (1 - again) times for each entry. That is the sum of the geometric series and it is the whole of Wu and Larus’s method in one line, which is why section 11.3 asks for it rather than for an iteration of the linear system until it settles.

Two things have to be true of again or this produces nonsense, and both are handled here rather than in the caller, because a division by nearly zero is the most common way a frequency implementation breaks. A loop with no predicted exit has again at certainty and the series does not converge, and one with an again a hair below certainty converges on a number no machine will run. So the count is capped at cap iterations, which is section 11.2’s max-predicted-iterations, and the cap is what a loop whose exit nothing predicted gets.

Source

pub fn is_hot_in_function(self, entry: Self) -> bool

Whether this block is hot compared with the rest of the function it is in.

Section 11.4, and GCC’s hot-bb-frequency-fraction: at least one part in HOT_BLOCK_FRACTION of the entry block. This is the question the register allocator and the loop passes are asking, and it is answerable with no profile at all, because it is a comparison between two blocks that were predicted the same way.

An entry frequency of zero is not a scale to be hot against, so nothing is hot in a function that never runs.

Source

pub const fn is_hot_in_program(self) -> Hotness

Whether this block is hot compared with the whole program.

A different question from Frequency::is_hot_in_function, which is why section 11.4 asks for two predicates named so they cannot be confused. The section placement decision wants this one: a block that runs a thousand times per call in a function called twice is hot in its function and cold in the program.

It is Hotness::Unknown today and will be until there is whole program profile data, which is document 35 and is after M4. The predicate exists now so that every caller is written against three answers from the start. A boolean that quietly means “hot, or we have no idea” is how cold code ends up in the hot section, and retrofitting the third answer into callers written against two is the part that does not happen.

Trait Implementations§

Source§

impl Clone for Frequency

Source§

fn clone(&self) -> Frequency

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Frequency

Source§

impl Debug for Frequency

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Frequency

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

As a multiple of the entry, to two decimal places, with the quality after it.

Source§

impl Eq for Frequency

Source§

impl Hash for Frequency

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for Frequency

Source§

fn cmp(&self, other: &Frequency) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl PartialEq for Frequency

Source§

fn eq(&self, other: &Frequency) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for Frequency

Source§

fn partial_cmp(&self, other: &Frequency) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl StructuralPartialEq for Frequency

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.