← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Inline Expansion

compiler Advanced
debt(d7/e3/b3/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'only careful code review or runtime testing' (d7). detection_hints.automated is 'no'; over-inlining causing code bloat and i-cache misses is silent until profiling or careful review of always_inline on large functions reveals it. No linter flags this.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). quick_fix is to write small focused functions and remove unwarranted inline hints, or manually-inlined bodies; a localised pattern replacement rather than a single-line swap, but contained.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Manual inlining or misplaced always_inline hurts readability and maintainability in the affected component, but the choice doesn't shape the whole system; it stays local to the hot path / helper.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception is that `inline` guarantees inlining — it is only a hint the cost model routinely overrides in both directions, contradicting the keyword's apparent meaning. Multiple common_mistakes (recursion depth limits, virtual-call inlining) reinforce a strong, counterintuitive gotcha.

About DEBT scoring →

Also Known As

inlining function inlining inline functions call site inlining

TL;DR

A compiler optimization that replaces a function call with the body of the called function, eliminating call overhead and unlocking further optimizations.

Explanation

In JIT runtimes such as the JVM HotSpot and V8, inlining decisions are made at runtime using profiling data: hot call sites are inlined and may be deoptimized if assumptions break. PHP 8's JIT performs more limited inlining and is far less aggressive than these mature runtimes.

Common Misconception

Marking a function `inline` guarantees the compiler will inline it. The keyword is only a hint; the compiler's cost model decides, and it routinely ignores or overrides such hints in both directions.

Why It Matters

Inlining is one of the highest-leverage optimizations because it both removes call overhead and exposes the callee to whole-program analysis, but over-inlining causes code bloat that degrades instruction cache performance.

Common Mistakes

  • Assuming the `inline` keyword forces inlining when it is merely a hint the optimizer may ignore.
  • Manually inlining function bodies by hand, hurting readability for a gain the compiler already provides automatically.
  • Expecting virtual or dynamically dispatched calls to be inlined without devirtualization or profile-guided information.
  • Over-applying always_inline to large functions, causing code bloat and instruction cache misses that slow execution.
  • Believing recursive functions can be fully inlined when compilers only inline a bounded depth.

Avoid When

  • The function body is large, since inlining copies it to every call site and causes code bloat.
  • Manually inlining by hand for readability-costly micro-optimizations the compiler already performs.
  • The call target is virtual or dynamic and cannot be resolved without devirtualization.

When To Use

  • Small, frequently called helpers like getters and accessors where call overhead dominates.
  • Hot loops where inlining exposes constant folding, vectorisation, or cross-boundary register allocation.
  • JIT runtimes inlining profiled hot call sites where runtime feedback confirms the benefit.

Code Examples

✗ Vulnerable
// C: forcing inlining of a large function hurts more than it helps
__attribute__((always_inline))
static inline int process(const int *data, int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += data[i] * data[i];      // large body
        if (data[i] < 0) sum -= 1;
        // ... many more lines ...
    }
    return sum;
}
// Called from 40 sites: body copied 40 times -> code bloat,
// instruction cache thrash, slower overall despite no call overhead.
✓ Fixed
// C: small hot helper, let the compiler decide
static inline int square(int x) {
    return x * x;        // tiny: a natural inlining candidate
}

int process(const int *data, int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += square(data[i]);   // compiler inlines square here,
    }                             // then hoists/vectorises the loop
    return sum;
}
// Large functions stay as real calls; the optimizer's cost model
// inlines only where the body is small and the benefit is real.

Added 1 Jun 2026
Views 3
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 3 pings M 1 ping T 1 ping W
ChatGPT 2 Google 2 Perplexity 1
crawler 3 crawler_json 2
DEV INTEL Tools & Severity
🔵 Info ⚙ Fix effort: Medium
⚡ Quick Fix
Write small focused functions and let the optimizer inline them; use inline hints only when profiling proves a specific call site needs it.
📦 Applies To
any cli library web
🔗 Prerequisites
🔍 Detection Hints
always_inline applied to large multi-statement functions, or manually copied function bodies repeated across call sites
Auto-detectable: ✗ No
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Medium Context: Function

✓ schema.org compliant