Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Optimizer hints

Hints tell the optimizer what it cannot see in the code. A hint never changes what a program computes, only how fast it runs, so a wrong hint costs speed and nothing else.

  • Which way a branch goes: write [Likely] or [Unlikely] above the if or match arm (see branch hints).
  • A function rarely called: [Cold] above it (see cold functions).
  • Memory a loop will soon touch: the hint module’s prefetches.
FunctionTells the optimizer
hint.prefetch_read(address)address will be read soon: start loading its cache line now.
hint.prefetch_write(address)address will be written soon.

A prefetch never faults, even for an address that is not mapped, and does nothing where the CPU has no prefetch instruction.

# Prefetching: start loading memory a loop will soon read.
import hint;

main(): int {
    var text = "a long text that a loop will read";
    hint.prefetch_read(text.c_str());
    var spaces = 0;
    for (var index in 0..text.length) {
        if (text.byte_at(index) == ' ') {
            spaces += 1;
        }
    }
    assert(spaces == 7, "a hint changes nothing the program computes");
    return 0;
}

The prefetches are LLVM’s llvm.prefetch intrinsic (see LLVM intrinsics). They matter only with optimization (-O2 and up, where the runtime’s functions inline into the caller); at -O0 they cost a call and do nothing.

Cold functions

[Cold] above a function, method or constructor marks it rarely called: the optimizer never inlines it and treats a call to it as the unlikely side of a branch. Split the rare work out of a hot function into a [Cold] one, so the hot function stays small enough to inline into its callers:

# A hot method with its rare work split out into a [Cold] one.
struct Counter {
    var count: int;
    var wraps: int;

    construct() {
        count = 0;
        wraps = 0;
    }

    # Called on every event: small enough to inline.
    add() {
        if (count == 1000) {
            _wrap();
        }
        count += 1;
    }

    # Called once per thousand events: kept out of line.
    [Cold]
    _wrap() {
        count = 0;
        wraps += 1;
    }
}

main(): int {
    var counter = Counter();
    for (var index in 0..2500) {
        counter.add();
    }
    assert(counter.wraps == 2 && counter.count == 500, "[Cold] changes nothing the program computes");
    return 0;
}

[Cold] is LLVM’s cold and noinline function attributes. The runtime’s allocator marks its slow paths this way.

Deprecated hints

hint.likely(condition) and hint.unlikely(condition) are deprecated: each use warns and suggests the attribute.