Energy & Power · Study deck
Software Optimization Techniques
Picture a battery sensor that wakes every second to ask whether anything happened.
Battery Bruno is your guide for this deck.

After studying this chapter
Learning objectives
You will be able to:
- Choose compiler and linker settings from evidence instead of habit.
- Identify when code size, memory traffic, active time, or wakeups dominate firmware cost.
- Apply data-layout and buffering changes that reduce copies and memory stalls.
- Decide when code-level changes such as inlining, lookup tables, or loop restructuring are worth the risk.
Major section
Start With Firmware That Wakes Too Often · In 60 Seconds
Most wake-ups do no useful work, yet each one starts clocks and code.
- Firmware means the software stored on the device.
- Duty cycle means the share of time a device spends active instead of asleep.
- This runway does not prove that every software change saves energy.
Major section
Firmware Optimization Loop
That sequence gives the visual its meaning: No-panel firmware optimization loop: profile, choose bottleneck, change one thing, test correctness, measure whole cycle, and record result.
- Unit tests, reference vectors, boundary cases, and integration run.
Major section
Code-Level Changes · Compiler And Build Choices
Compiler flags are a starting point, not an optimization strategy by themselves.
- You need readable stepping, assertions, and source-level diagnosis.
- The product needs stable speed without aggressive code growth.
- Flash, update size, or instruction fetch is the limit.
- A measured hot path blocks a deadline or keeps the device awake.
Major section
Data, Memory, And Copies · Event-Driven Sleep
Data movement can dominate firmware cost.
- A clean algorithm can still waste energy if it copies buffers, parses verbose payloads, or wakes the CPU for every small transfer.
- Busy waiting is one of the easiest ways to waste energy.
- Replacing a polling loop is only useful if firmware has a complete route back to sleep.
Major section
Polling Keeps The Core Awake; Events Let It Sleep
In particular, Runs normally must be reconciled with: Sleeps until an event before the result can guide implementation.
- With those jobs separated, the chapter's polling keeps the core awake; events let it sleep claim remains testable.
Major section
Phoebe's Field Notes: Why "More Than 8000 Days" Is A Ceiling, Not A Forecast · delay() Does Not Sleep, And You Must Offload The Watching
The mathematical gist.: A 2,000 mAh, 3.7 V pack stores 7.40 Wh at nameplate conditions.
- At 2% monthly self-discharge, 29.8% remains after five years and 8.85% after ten, so an ideal 8,000-day current-draw ceiling is not a field-life promise.
Major section
Compiler Optimization Modes
Optimization flags express a preference to a particular toolchain; they do not guarantee a fixed list of transformations.
- In common GCC- and Clang-style workflows, a speed-focused -O3 build may inline more aggressively, unroll or vectorize loops, reorder instructions, and create separate fast paths for alignment or aliasing cases.
- A size-focused -Os build usually discourages growth, favors shorter encodings, and may keep branches or calls that a speed build removes.
- A size build can reduce fetch energy, yet keep the core awake longer.
- The winning flag is the one that lowers measured charge per useful task while preserving timing, stack, numerical, and update-slot requirements.
Major section
Code Density and Instruction-Level Parallelism
Code occupies silicon and consumes energy every time it is fetched.
- A memory large enough to hold software can dwarf a small processor core, so instruction density can affect area, fetch bandwidth, leakage, and update time.
- Compressed instruction sets commonly provide short 16-bit encodings alongside wider 32-bit encodings.
Major section
Code Density and Instruction-Level Parallelism (continued)
VLIW therefore exchanges dynamic scheduling hardware for compiler scheduling and can waste code space when parallelism is sparse.
- Short forms save bytes but have fewer encoding bits, so they may expose only a subset of registers, smaller immediate ranges, fewer addressing modes, or an explicit mode/history constraint on older designs.
- The assembler expands to a wider form when operands do not fit.
- None is a reliable proxy for the other two.
Major section
Vectorization and Tail Handling
The: TAIL [8 9] then branches to masked lanes or scalar cleanup, so the speedup boundary includes setup and remainder work and never reads beyond x[9] merely to fill a vector.
- The vector loop executes $q$ times over $qW$ elements; a tail path handles the remaining $r$ elements.
Major section
Vectorization and Tail Handling (continued)
For $N=18$ and $W=4$, there are four vector iterations covering 16 elements and two scalar tail iterations.
- Omitting the tail silently leaves c[16] and c[17] wrong.
- Some instruction sets provide masked loads and stores, allowing one final vector operation with only the first $r$ lanes enabled.
- so short arrays, tails, alignment repair, alias checks, and memory bandwidth reduce the gain.
Major section
Predication and Function Inlining · Summary
Below,: CALL / RETURN keeps one 12 B body, while: INLINE AT THREE SITES removes call overhead at the explicit cost of +24 B image growth.
- If its direction is hard to predict, a misprediction flushes useful pipeline work.
- For a branch with misprediction probability $p_m$ and recovery cost $L$ cycles, the expected branch penalty is approximately $p_mL$.
Deck summary
Key takeaways
Most wake-ups do no useful work, yet each one starts clocks and code.
- That sequence gives the visual its meaning: No-panel firmware optimization loop: profile, choose bottleneck, change one thing, test correctness, measure whole cycle, and record result.
- Compiler flags are a starting point, not an optimization strategy by themselves.
- Data movement can dominate firmware cost.
- In particular, Runs normally must be reconciled with: Sleeps until an event before the result can guide implementation.
Retrieval practice
Recall check 1 of 6

Battery Bruno says: answer from memory, then check your reasoning.
Q1A profile shows firmware spends much of its active window waiting for a peripheral transfer to complete. Which software optimization should be evaluated first?
Show answer
Answer: B Optimization follows the measured bottleneck.
Retrieval practice
Recall check 2 of 6

Battery Bruno says: answer from memory, then check your reasoning.
Q2A speed-focused build reduces one hot function's runtime but grows the firmware enough to threaten over-the-air update limits. What is the best next step?
Show answer
Answer: B Software optimization is multidimensional.
Retrieval practice
Recall check 3 of 6

Battery Bruno says: answer from memory, then check your reasoning.
Q3Place each software optimization artifact where it lives so you can change the measured hot path without trading away timing, memory, or energy safety.
Show answer
Answer: A Link measured hot-path evidence to explicit build and firmware changes, then replay the same workload and guardrails so you can prove the optimization rather than infer it.
Retrieval practice
Recall check 4 of 6

Battery Bruno says: answer from memory, then check your reasoning.
Q4Why does an event-driven firmware structure usually beat a polling loop on battery life by a large margin?
Show answer
Answer: B Polling keeps the core active at milliamps while event-driven firmware sleeps at microamps and wakes only on real events.
Retrieval practice
Recall check 5 of 6

Battery Bruno says: answer from memory, then check your reasoning.
Q5A node handles about 10 events per hour, each 5 ms at 8 mA, and can sleep at 10 uA. What is the approximate average current if it is event-driven rather than polling at 8 mA?
Show answer
Answer: A The bursts contribute 0.4 mA-s per hour, or about 0.11 uA averaged. Add the 10 uA sleep floor for roughly 10.1 uA total, about 800x below 8 mA polling.
Retrieval practice
Recall check 6 of 6

Battery Bruno says: answer from memory, then check your reasoning.
Q6A firmware author changes fixed-interval reporting to use delay(1000) between reports expecting big energy savings, but the average current barely drops. Why?
Show answer
Answer: C A spinning delay produces the timing but not the energy saving, because the core stays active the whole second.
Print reference
Answers 1 of 2
Answer key.
- B · Optimization follows the measured bottleneck.
- B · Software optimization is multidimensional.
- A · Link measured hot-path evidence to explicit build and firmware changes, then replay the same workload and guardrails so you can prove the optimization rather than infer it.
- B · Polling keeps the core active at milliamps while event-driven firmware sleeps at microamps and wakes only on real events.
Print reference
Answers 2 of 2
Answer key.
- A · The bursts contribute 0.4 mA-s per hour, or about 0.11 uA averaged. Add the 10 uA sleep floor for roughly 10.1 uA total, about 800x below 8 mA polling.
- C · A spinning delay produces the timing but not the energy saving, because the core stays active the whole second.