AYOUB.*
← EMERGING SYSTEMS ENGINEERINGREPOS ↗

Chapter 8 · Part III: Quantum Software Engineering and High-Efficiency Compute

Sustainable and Green Software Engineering

Software has no emissions. The hardware it runs on does, and the amount depends on decisions an engineer makes: how much work the code does, how densely it is packed, when it runs, and how long its data is kept. This chapter covers how to measure each of those and what actually moves them.

In this chapter
  1. 8.1 Energy-Aware Code Profiling
  2. 8.2 Power-Efficient System Architecture
  3. 8.3 Resource Density Optimization
  4. 8.4 Sustainable Storage and Data Lifecycle Management
  5. Sources and further reading

8.1 Energy-Aware Code Profiling

Energy is power integrated over time. A program's energy cost is therefore its power draw multiplied by its runtime, which means that making code faster usually makes it greener, and that the two goals align far more often than they conflict.

Emissions are energy multiplied by the carbon intensity of the electricity that supplied it, and that intensity varies by a factor of ten between regions and by a factor of three within one region across a day.

The measurement stack

Four layers of measurement exist, and they differ in accuracy and in what they can attribute.

A wall power meter is the ground truth. It measures the whole machine including power supply losses, fans, and idle draw. It cannot attribute anything to a process.

On-chip energy counters are the practical instrument. Intel's Running Average Power Limit interface and the AMD equivalent report accumulated energy for the package, the cores, and the memory controller. Accuracy against a wall meter is typically within a few percent. Accelerator vendors expose equivalent counters.

Model-based estimation attributes energy to a process by combining the machine-level counters with per-process resource use. It is what most software tools do, and its accuracy depends entirely on the model.

Cloud provider reporting gives account-level emissions data, on a delay, at coarse granularity, with methodologies that differ between providers and that change.

# On-chip energy counters. The delta divided by elapsed time is watts.
# The file is root-readable only on recent kernels, for a side-channel
# reason worth knowing about.
E0=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)
sleep 10
E1=$(cat /sys/class/powercap/intel-rapl:0/energy_uj)
echo "package: $(( (E1 - E0) / 10000000 )) W average"

# perf reads the same counters and attributes to a command.
perf stat -a -e power/energy-pkg/,power/energy-ram/ -- ./workload

# Accelerator draw, sampled.
nvidia-smi --query-gpu=power.draw,utilization.gpu \
           --format=csv --loop-ms=200

# Per-process attribution, model-based.
powertop --time=30 --csv=power.csv

Table 8.1: where the energy goes in a server

Component Idle Typical load Peak Note
CPU, 64 core 40 to 70 W 150 to 250 W 350 to 400 W scales with frequency cubed
DRAM, 1 TiB 30 to 50 W 60 to 90 W 120 W mostly refresh, load-insensitive
NVMe SSD, per drive 2 to 5 W 8 to 15 W 25 W
Network card, 100 Gb 15 to 25 W 25 to 35 W 40 W load-insensitive
Accelerator, per device 60 to 100 W 400 to 700 W 700 to 1,400 W dominates when present
Fans and losses 30 to 60 W 60 to 120 W 200 W rises sharply with heat
Whole server, no accelerator 150 to 250 W 400 to 600 W 900 W
Whole server, 8 accelerators 700 to 1,000 W 4,000 to 6,000 W 12,000 W

Two rows carry most of the design consequence. Idle draw is 30 to 50 percent of peak, which means an idle server costs roughly a third of a busy one and produces nothing. That single ratio is why the density work in Section 8.3 is the largest available lever for most organizations.

And accelerators dominate everything else when present. An eight-accelerator node draws more than twenty ordinary servers, so an organization with a significant accelerator fleet has an energy problem that is almost entirely an accelerator utilization problem.

The Software Carbon Intensity specification

The Green Software Foundation's SCI specification became the first ISO-aligned standard for measuring the carbon impact of software, and its value is that it defines a rate rather than a total.

The formula is that SCI equals energy times carbon intensity, plus embodied emissions, all divided by a functional unit. Energy is what the software consumed. Carbon intensity is the grams of carbon dioxide equivalent per kilowatt hour of the supplying grid at that place and time. Embodied emissions are the manufacturing footprint of the hardware, amortized over its lifetime and the share this software used. The functional unit is per request, per user, per transaction, or whatever the software's own unit of work is.

Dividing by a functional unit is the design decision that makes the metric useful. A total goes up when a business grows, which tells you nothing about whether the software improved. A rate falls when the software gets more efficient regardless of scale, which is what an engineering team can act on.

Embodied emissions deserve attention because they are routinely omitted and they are large. Manufacturing a server accounts for a substantial share of its lifetime emissions, and for a device that is lightly used it can exceed the operational share. That fact has a direct engineering consequence: extending hardware life and raising utilization both reduce emissions in ways that a purely operational measurement cannot see.

What actually reduces energy in code

The optimizations that reduce energy are, with few exceptions, the optimizations that reduce time. Volume I covers the mechanisms and this is the energy reading of the same list.

Algorithmic improvement dominates everything. An order-of-magnitude reduction in work is an order-of-magnitude reduction in energy, and no amount of micro-optimization competes with it.

Memory locality matters more for energy than for time. Moving a cache line from DRAM costs roughly two orders of magnitude more energy than an arithmetic operation on register data. A layout change that turns random access into sequential access therefore saves energy out of proportion to its speed gain.

Language and runtime choice shows a wide spread in published comparisons, and the honest framing is that the spread mostly tracks execution time and allocation rate rather than anything intrinsic. A compiled language with manual or ownership-based memory management sits at one end and an interpreted dynamic language at the other, with an order of magnitude between them for compute-heavy work and much less for I/O-bound work.

Avoiding work is the largest lever that does not appear in a profile. A cached result costs nothing to compute. A request that is never made costs nothing to serve. A polling loop replaced by an event subscription costs nothing while idle, and a busy-wait loop is the purest form of energy waste, because it consumes full power to accomplish precisely nothing.

The one genuine divergence between speed and energy is worth naming. Running at a lower clock frequency reduces power more than proportionally, because dynamic power scales with the cube of frequency in the relevant range. A workload with slack finishes later and uses less total energy at a lower frequency. A workload with a latency target does not have that slack, which is why race to idle is the right strategy for interactive work and frequency reduction is the right strategy for background batch work.

8.2 Power-Efficient System Architecture

Carbon intensity varies enormously by place and by time. That variation is the lever, because a workload that is flexible about when or where it runs can be placed in a low-carbon window at no cost to its result.

The variation

Grid carbon intensity spans roughly 20 grams of carbon dioxide equivalent per kilowatt hour in a hydro- or nuclear-dominated region to 700 or more in a coal-dominated one. That is a factor of thirty between regions.

Within one region, intensity varies by a factor of two to four across a day and across seasons, following solar output, wind, and demand. A grid with significant solar capacity has a pronounced midday trough and a sharp evening peak as solar falls and demand rises.

Both variations are published in near real time by grid operators and by several data services, with forecasts hours ahead, which is what makes scheduling against them possible.

Three shifting strategies

Temporal shifting moves flexible work to a low-intensity window in the same region. A nightly batch job, a machine learning training run, a backup, a report generation, and a large data migration are all candidates, because none has a user waiting.

Spatial shifting moves work to a low-intensity region. It is effective, and it is constrained by data residency law, by data gravity, and by the transfer cost of moving the inputs.

Demand shaping changes the work rather than moving it. Reduce video quality when the grid is dirty, defer a non-essential background sync, lower a model's precision, or reduce a prefetch aggressiveness. It applies where the classical shifting strategies do not, which is interactive work.

  gCO2e/kWh
  450 |                                                    ####
  400 |  ####                                          ########
  350 |  ########                                  ############
  300 |  ############                          ################
  250 |      ############                  ####################
  200 |          ############          ########################
  150 |              ################################
  100 |                    ####################
   50 |
      +------------------------------------------------------------
      00   03   06   09   12   15   18   21   00
                          ^^^^^^^^^^^^                ^^^^^^^^
                          solar trough                evening peak
                          run batch here              defer here

  Same work, same region, same total energy:
    training run at 13:00  ->  120 gCO2e/kWh
    training run at 19:00  ->  430 gCO2e/kWh
  A 3.6x emissions difference from a scheduling decision alone.

Figure 8.1 A day of grid intensity, and where flexible work belongs.

A carbon-aware scheduler needs four inputs: a forecast of intensity, a deadline for the work, an estimate of its duration, and a power estimate. It then places the job in the lowest-intensity window that meets the deadline. The logic is straightforward and the integration work is in exposing the deadline, because most batch systems have no concept of one.

Datacenters as grid participants

The most interesting recent development inverts the relationship. Rather than scheduling around the grid, a large compute facility becomes a resource that the grid can call on.

A demonstration in London in March 2026, run with a national grid operator and industry partners, showed high-performance accelerator infrastructure operating as a grid-responsive asset without disrupting critical workloads. The facility reduced or shifted flexible load in response to grid conditions, which converts a large inflexible consumer into a flexible one.

The engineering requirement is a workload classification that the scheduler can act on. Interactive inference is not interruptible. Training is interruptible with checkpointing. Batch analytics is deferrable by hours. A facility that knows which of its load is in each class can respond to a grid signal, and one that treats all load as equally critical cannot.

Table 8.2: the levers, and their realistic size

Lever Typical reduction Effort Constraint
Right-size over-provisioned resources 20 to 50 percent low needs measurement
Raise cluster density 20 to 40 percent medium scheduling and isolation
Scale to zero when idle 30 to 90 percent of idle medium cold start latency
Temporal shifting of batch work 15 to 40 percent medium needs deadlines
Spatial shifting to a clean region up to 30x for that work medium residency, data gravity
Algorithmic improvement 10x to 1000x high engineering time
Caching and avoided work varies, often large low to medium correctness
Language or runtime change 2 to 10x for compute-bound high rewrite cost
Extend hardware lifetime reduces embodied share low performance and support
Storage tiering and deletion 50 to 90 percent of storage low policy and compliance

The first row is the one to start with and it is consistently the largest immediate win. Most workloads request several times the resources they use, because the request was a guess that nobody revisited, and the gap is paid for in hardware that runs idle.

Be careful with efficiency claims, including your own

Three traps recur. Reporting a total rather than a rate lets a genuine efficiency improvement look like a regression during growth, and the reverse. Reporting operational emissions only omits embodied emissions, which for lightly used hardware can be the larger share. And an efficiency gain that enables more consumption can raise total emissions, which is the rebound effect and is well documented. Report the rate and the total together, include embodied emissions, and state the methodology, because a number without a methodology is not comparable to anything.

8.3 Resource Density Optimization

Idle infrastructure is the largest and least glamorous source of waste. A server at 10 percent utilization draws roughly half the power of one at 90 percent while doing a ninth of the work, so consolidation is close to free efficiency.

Industry utilization figures are consistently poor. Typical enterprise server utilization sits in the 10 to 30 percent range, and Kubernetes clusters frequently show requested resources at several times actual use, because requests are set once from a guess.

Right-sizing

The gap between requested and used is the first thing to close, and it is mostly a measurement problem rather than an engineering one.

Measure actual use at a percentile rather than a mean, because a mean under-provisions for the peak and a maximum over-provisions for an outlier. The p95 or p99 of CPU over a representative period, with headroom, is the defensible basis.

Set memory request equal to memory limit, because memory is not compressible and a container that exceeds its limit is killed rather than slowed. Set CPU requests from measured use and, as Volume II argues, omit CPU limits unless a hard cap is contractually required, because a CPU limit throttles a container while the node has idle capacity.

Automate it. Vertical autoscaling that recommends or applies request values from observed use removes the guess permanently, and the recommendation is more accurate than any human estimate because it is based on the actual workload.

Bin packing

Once requests are accurate, the scheduler's job is to pack work onto as few machines as possible. That is a bin packing problem, it is NP-hard, and heuristics get close.

Two scheduling policies define the trade. A spread policy distributes pods across nodes, which improves resilience to a node failure and leaves every node partly empty. A bin-packing policy fills each node before using the next, which raises density and concentrates the impact of a node failure.

The right answer is different per workload class and a cluster can run both. A stateless service with many replicas wants spread across failure domains. A batch job wants packing. Node pools with different policies, and a scheduler configuration that directs each class to the right pool, gives both.

Two obstacles limit packing in practice. Resource fragmentation leaves gaps too small for any pending pod, which a periodic descheduler addresses by evicting pods so the scheduler can place them better. And the largest pod sets the minimum node size, so one pod requesting 60 percent of a node prevents any useful packing around it.

Scaling to zero

A service with no traffic consuming no resources is the ideal, and cold start latency is what stands between the ideal and the deployment.

The shape is consistent. A container starts in hundreds of milliseconds, a microVM in around 125 milliseconds, a V8 isolate in one to five, and a WebAssembly module in under one.

The decision is a straightforward arithmetic one. If a service receives a request every few seconds, scaling to zero saves nothing and adds latency to the occasional cold request. If it receives a request every few minutes, or in concentrated bursts, scaling to zero saves most of its cost. Internal tools, development environments, batch triggers, and long-tail services are the candidates, and they are usually the majority of an organization's service count while being a small share of its traffic.

Three techniques reduce the cold start cost where scale-to-zero is otherwise too slow. Snapshot and restore captures a warmed process image and restores it, which removes initialization entirely. Lazy image pulling starts the container before the image has fully downloaded, which Volume II covers and which matters most for large images. And keeping one warm instance while scaling the rest to zero eliminates the user-visible cold start at a small fixed cost.

The density programme that works, in order

Measure request against use for every workload and publish the ratio per team, because visibility alone closes a surprising share of the gap. Enable vertical autoscaling in recommendation mode, then in apply mode for non-critical workloads. Separate node pools by scheduling policy so that batch packs and stateless services spread. Move development and internal tooling to scale-to-zero, which is where the cold start cost is acceptable and the idle time is highest. Then run a descheduler for fragmentation. That sequence gets most of the available reduction before any application change is needed.

8.4 Sustainable Storage and Data Lifecycle Management

Storage grows monotonically unless something deletes. The default behavior of almost every system is to keep everything forever, which is a decision that nobody makes and everybody pays for.

The tiering arithmetic

Storage tiers differ by roughly two orders of magnitude in cost and in energy, and the difference comes from whether the medium spins, is powered, or is mounted at all.

Table 8.3: storage tiers, cost and access characteristics

Tier Relative cost Access latency Typical use
Local NVMe 100 microseconds hot working set
Network block storage 40 sub-millisecond databases, volumes
Object storage, standard 10 tens of milliseconds active data
Object storage, infrequent access 5 tens of milliseconds monthly access
Object storage, archive 1.5 minutes to hours compliance retention
Object storage, deep archive 0.5 up to 12 hours legal hold
Deleted 0 not available everything past its purpose

The last row is the one that organizations skip and it is where the largest reduction is. Data that serves no purpose costs money, costs energy, and constitutes a liability under every privacy regulation, because a record that does not exist cannot be breached or mishandled.

Lifecycle policies automate the movement, and three cautions decide whether they work. Retrieval from a deep archive costs money and hours, so the policy must match the actual access pattern rather than an assumed one. Small objects carry a minimum billable size in most archive tiers, so archiving millions of small files is frequently more expensive than keeping them. And a minimum storage duration applies, so moving an object to archive and deleting it a week later costs more than leaving it.

Deduplication and compression

Deduplication removes identical blocks. Content-addressed storage does it inherently, because identical content has an identical address. Reported ratios run from 2 to 10 times for backups and virtual machine images and much less for already-unique data.

Compression is chosen per tier by a simple rule: use a fast algorithm for hot data where decompression is on the read path, and a slow high-ratio algorithm for cold data where nothing is waiting. Use Zstandard at a low level for hot data and at a high level for cold data. Use columnar encoding for analytical data, which routinely gives five to twenty times on real data.

Compression saves more than storage. It reduces network transfer and often improves query speed, because less data crosses the slowest boundary. That effect makes compression one of the few choices that improves cost, energy, and performance at once.

Logs and telemetry

Observability data is frequently the largest storage line item and the least examined, and most of it is never read.

Four controls address it and they compose. Sample high-volume informational logs at a low rate and keep every warning and error. Set retention by value rather than uniformly: days for debug, weeks for informational, months for audit. Move the audit subset to a separate cheap append-only store, because it has a different access pattern and a different regulatory basis. And aggregate at the collector rather than shipping raw records, which Volume II covers.

The measurement worth running is simple and uncomfortable. Instrument which log streams and which dashboards are actually queried over a quarter. The consistent finding is that a large majority of retained telemetry is never read, and that finding is what makes the retention conversation possible.

Retention as a policy problem

Retention is not primarily a technical decision. It is a policy decision that needs an owner, and the technical work is enforcement.

Every dataset needs four attributes: a purpose, a legal basis, a retention period, and an owner. A dataset with no stated purpose has no defensible retention period, which is the situation most data is in.

Two mechanisms then do the work. Automatic expiry attaches a lifecycle rule at write time rather than applying one later, so nothing accumulates without a plan. And deletion must be tested, because a deletion path that has never been exercised does not work, and the first time it is exercised is usually under a regulatory request with a deadline.

Volume II describes crypto shredding for the case where an append-only log cannot delete: encrypt each subject's data under a per-subject key and delete the key. That pattern applies here too, and it is the answer for any immutable store that must honor an erasure request.

Sources and further reading

The Green Software Foundation's Software Carbon Intensity specification and its supporting material, including the current definition of green software. The Principles of Green Software Engineering. Pereira and others on energy efficiency across programming languages, read with attention to methodology. The published work on carbon-aware scheduling for batch and serverless workloads, and on testbeds for carbon-aware systems. Grid operator real-time intensity data services and their forecast APIs. The Linux powercap and perf documentation for the energy counters. Cloud provider sustainability methodology documents, read comparatively, since the methodologies differ.

What this chapter established

  • Energy is power times time, so most speed optimizations are also energy optimizations. Emissions add the grid's carbon intensity, which varies thirtyfold by region and severalfold by hour.
  • On-chip energy counters are the practical instrument and land within a few percent of a wall meter. They measure the machine, and attribution to a process is a model.
  • Idle draw is 30 to 50 percent of peak, which makes density the largest available lever for most organizations.
  • An eight-accelerator node draws more than twenty ordinary servers, so an accelerator fleet's energy problem is an accelerator utilization problem.
  • SCI divides by a functional unit, which makes it a rate that falls when software improves rather than a total that rises when a business grows.
  • Embodied emissions are routinely omitted and can exceed operational emissions for lightly used hardware. Extending hardware life and raising utilization both reduce them.
  • Moving a cache line from DRAM costs about two orders of magnitude more energy than an arithmetic operation, so locality improvements save energy out of proportion to their speed gain.
  • Race to idle is right for latency-sensitive work and frequency reduction is right for background work, because dynamic power scales with the cube of frequency.
  • Temporal shifting, spatial shifting, and demand shaping are the three levers on carbon intensity. All three need a deadline that most batch systems do not express.
  • A facility that classifies its load as interruptible, deferrable, or critical can respond to a grid signal. One that treats all load as critical cannot.
  • Right-sizing over-provisioned requests is the largest immediate win, and it is a measurement problem rather than an engineering one.
  • Spread improves resilience and packing improves density. Run separate node pools and direct each workload class to the right one.
  • Scale to zero pays for services with sparse or bursty traffic, which is usually most of an organization's service count and little of its traffic.
  • The cheapest storage tier is deletion, and data past its purpose is a cost, an energy draw, and a privacy liability at once.
  • Archive tiers carry minimum object sizes, minimum durations, and retrieval costs. A lifecycle policy that ignores them costs more than no policy.
  • Most retained telemetry is never read. Measure which streams are queried before negotiating retention.
  • Every dataset needs a purpose, a legal basis, a retention period, and an owner. Attach expiry at write time, and test the deletion path before a regulator does.

Chapter 8 of Emerging Systems Engineering, revision 1.0. Attribution and sole author credit: Ayoub Zulfiqar.