Course contentsShow
← Rust
Lesson 1602 of 1,91013. Metaprogramming with MacrosFree lesson

Optimized Compile-Time Lookup Tables

You will generate constant-time lookup tables from complex initial values during the build process.

In this lesson, you will learn how to shift expensive runtime computations into the binary’s data segment by generating optimized, read-only lookup tables during macro expansion.

The Problem: Runtime Overhead

In high-performance applications, we often need to calculate complex mathematical functions (like trigonometric tables, CRC constants, or state-transition matrices). Computing these at runtime is costly, but hard-coding them manually is error-prone and unmaintainable. We want the performance of a constant array with the expressiveness of procedural logic.

The Solution: Macro-Generated Tables

By using a procedural macro, we can execute arbitrary Rust code during the compilation phase to produce a const array. This embeds the result directly into your program's data segment, meaning the "calculation" cost is effectively zero at execution time.

Consider a case where we need a table of pre-computed sine values for a custom fixed-point DSP library:

// In your proc-macro crate
#[proc_macro]
pub fn generate_sine_table(_item: TokenStream) -> TokenStream {
    let table: Vec<f64> = (0..256)
        .map(|i| (i as f64 * std::f64::consts::PI / 128.0).sin())
        .collect();
    
    quote! {
        pub const SINE_TABLE: [f64; 256] = [#(#table),*];
    }.into()
}

Why This Is "Advanced"

When generating these tables, you must consider memory layout and cache alignment. By using macros, you can not only generate the values but also apply attributes like #[repr(align(64))] to ensure the table sits perfectly on cache lines, preventing "false sharing" or cache misses.

Furthermore, because this happens at compile time, the compiler treats the resulting const array as a static literal. This enables the optimizer (LLVM) to perform aggressive constant folding or even replace calls to your lookup function with the direct value if the index is known at compile time. You are essentially using the macro system as a custom pre-compiler that guarantees your "runtime" code is just a simple pointer offset.

Key Takeaway: Shift complex logic into procedural macros to bake computed results into the binary, trading compilation time for zero-cost runtime performance.