The Fastest Code Is the Code Whose Costs You Can See

min dulle

Hatched by min dulle

Aug 10, 2026

10 min read

86%

0

What if the fastest program is not the one with the cleverest optimization, but the one whose behavior is easiest to reason about?

That question sits at the intersection of two disciplines that are often treated as opposites. Functional thinking emphasizes transformation, composition, immutability, and expressions whose meaning can be understood independently of their surroundings. Performance work emphasizes measurement, resource limits, memory behavior, latency, and the physical cost of computation.

One seems concerned with elegance. The other seems concerned with machinery.

In practice, they are deeply connected. The ability to make a program fast depends on the ability to see what the program is doing. Functional thinking can make that behavior clearer, but only if it is applied with a serious understanding of cost. Performance optimization, in turn, becomes more reliable when it preserves clear functional boundaries instead of turning the entire codebase into an improvised collection of exceptions.

The central lesson is this: performance is not merely a property of hardware usage. It is a property of how clearly a program exposes its causes and effects.

The Hidden Enemy Is Not Slowness, but Uncertainty

When engineers say that a system is slow, they often mean several different things. A page may take too long to become interactive. A database query may consume too much memory. A service may respond quickly under light traffic but collapse under concurrency. A batch job may finish in an acceptable amount of time while quietly wasting most of its compute budget.

These are not interchangeable problems. Each has a different bottleneck, and each demands a different intervention. Yet teams frequently begin with the same instinct: find a line of code that looks inefficient and change it.

That instinct is unreliable because the visible code is often far removed from the actual cause. A loop may be slow because it repeatedly allocates objects. A function may be expensive because it triggers a network request hidden inside a convenience method. A user interface may rerender because an apparently harmless update changes an identity that the framework uses to decide what must be rebuilt.

The first requirement of optimization is therefore not cleverness. It is causal visibility.

A functional style can help because it encourages developers to describe computation as a series of transformations. Given an input, produce an output. Compose one operation with another. Keep side effects near the edges. When those boundaries are real, the cost of a computation becomes easier to inspect.

Consider a data pipeline that loads records, filters invalid entries, groups the survivors, and calculates totals. If these operations are ordinary, composable transformations, an engineer can ask precise questions. How many records enter each stage? Which stage increases memory usage? Is grouping necessary before filtering? Can the aggregation happen in one pass?

If the same behavior is scattered across callbacks, mutable global state, database triggers, cache invalidations, and hidden logging, the questions become much harder. The system may still work, but its performance has become an archaeological problem.

The first performance optimization is often making the program’s behavior legible enough to measure.

Functional Clarity Meets Physical Reality

Functional thinking does not automatically produce fast software. A beautifully composed pipeline can be slower than a direct loop. An immutable update can allocate an entire tree when a localized mutation would have been cheaper. A sequence of elegant abstractions can prevent the compiler from optimizing effectively or make the runtime traverse the same data repeatedly.

This is not a failure of functional ideas. It is a reminder that semantic clarity and physical efficiency are different dimensions.

Imagine processing one million numbers. These two designs may express the same result:

numbers
  filter isValid
  map normalize
  map extractValue
  sum

and:

for each number:
    if it is valid:
        add its normalized value to the total

The first design makes the conceptual stages obvious. The second may perform fewer passes and create fewer intermediate structures. Depending on the language and runtime, the difference could be negligible, or it could be substantial.

The mature response is not to choose one style dogmatically. It is to separate two questions:

  1. What transformation does the program mean?
  2. What execution strategy delivers that meaning within the required budget?

This distinction creates a powerful design pattern. First express the computation in a form that is easy to understand and test. Then choose an implementation strategy that meets the observed performance requirement. The optimized version should preserve the same visible contract, even if its internal execution is more specialized.

This is the same relationship that exists between a mathematical formula and an efficient numerical method. The formula states the result. The method determines how to obtain it with limited time and memory.

The danger lies at both extremes. If abstraction is allowed to conceal cost, engineers may mistake a convenient expression for a cheap one. If optimization is allowed to destroy structure, engineers may reduce a system’s performance problem while creating a maintenance problem that will cost more for years.

A useful rule is: make expensive behavior explicit, and make optimized behavior locally replaceable.

A function that performs a network request should not look indistinguishable from a pure calculation. A transformation that copies a large collection should not hide behind a method name that suggests a constant cost. A cache should expose its invalidation policy. An operation that may block should make that possibility visible in its interface or surrounding architecture.

The goal is not to eliminate abstraction. It is to prevent abstraction from becoming a false promise about cost.

The Performance Meaning of Composition

Composition is usually praised because it lets us build large behaviors from small parts. Its performance significance is more subtle: composition creates optimization boundaries.

Suppose a request handler consists of five stages. Each stage has a clear input and output. The system can measure each stage independently, replace one implementation without changing the others, and test the whole chain against a stable contract. This structure makes profiling useful because a slow stage has a recognizable location and responsibility.

Now suppose the stages share mutable state, mutate each other’s inputs, and depend on call order. The same request may behave differently depending on what ran earlier. A performance measurement taken in one context may not apply in another. An optimization that improves one path may silently damage another.

Functional composition helps create what might be called cost locality. A cost is local when an engineer can identify where it originates, what inputs affect it, and what downstream behavior it influences.

Cost locality matters in several familiar situations:

  • In a user interface, a component should make it possible to see why it rerenders and how much work that rerender performs.
  • In a data service, a query builder should make it possible to distinguish local computation from remote execution.
  • In a concurrent system, an operation should make its synchronization or contention costs visible rather than burying them inside unrelated helpers.
  • In a collection pipeline, the number of passes, allocations, and materialized intermediates should be understandable from the structure of the computation.

This suggests a useful mental model: treat every function as having two signatures. The first is its semantic signature, which describes what it returns. The second is its resource signature, which describes what it consumes.

A semantic signature might say:

Customer records become monthly summaries

A resource signature adds:

One database read, memory proportional to the number of customers, one pass over the records, and no external mutation

Most programming languages enforce only the first signature. High quality engineering practice makes the second one visible through naming, documentation, measurements, architecture, and tests.

Once resource signatures are visible, optimization becomes a form of composition too. One can replace a linear search with an indexed lookup, a repeated computation with memoization, or a sequence of remote calls with a batched request, while preserving the semantic signature.

Why Measurement Belongs Inside the Design

A common performance mistake is to treat measurement as a final audit. Teams build a system, discover that it is slow, and then attach profiling tools to the outside. By that point, the design may make meaningful measurement difficult.

A more durable approach is to design for feedback from the beginning. This does not mean instrumenting every line. It means choosing boundaries where time, memory, throughput, and failure can be observed.

Functional thinking supports this because pure transformations are easier to test with representative inputs. If a transformation is deterministic, a benchmark can run it repeatedly and compare results across implementations. If it has no hidden external effects, a profiler can examine its cost without also modeling unpredictable interactions with the rest of the system.

Measurement also disciplines intuition. Developers routinely misjudge which operations matter. A small allocation inside a frequently called function may dominate a large but rare computation. A database query that looks complex may be fast because of an index, while a simple looking query may scan millions of rows. A microbenchmark may show improvement in isolation while the full application remains unchanged because the actual bottleneck is elsewhere.

The right sequence is therefore not “optimize everything that looks suspicious.” It is:

  1. Define the performance property that matters.
  2. Establish a representative workload.
  3. Measure the whole path.
  4. Locate the dominant cost.
  5. Form one hypothesis.
  6. Change one meaningful variable.
  7. Measure again under the same conditions.

This process resembles scientific reasoning because performance work is an empirical activity. The code expresses a theory about how work should happen. The measurement reveals how work actually happens.

There is an important connection here to referential transparency. When the same input reliably produces the same result, it becomes easier to compare versions. The fewer hidden variables involved, the more trustworthy the experiment. Functional design does not remove the need for profiling, but it can improve the quality of the evidence profiling produces.

A Practical Framework: Meaning, Movement, and Multiplicity

When a computation is too slow, analyze it through three questions.

1. Meaning: What result is required?

State the computation without describing its current implementation. Is the system finding the first matching record, sorting every record, or merely checking whether a match exists? Is the interface calculating a new layout, or is it repeatedly recalculating a layout that has not changed?

Many performance problems begin with doing more work than the result requires. If the question is whether any item satisfies a condition, scanning the entire collection after finding the first match is unnecessary. If only the top ten results are needed, fully sorting a million records may be the wrong algorithm.

2. Movement: Where does the data travel?

Data movement is often more expensive than the operation applied to the data. Moving records from a database to an application, copying arrays between layers, converting objects between formats, and transferring data across process boundaries can dominate the arithmetic itself.

Functional composition makes transformations visible, but it can also encourage a chain of intermediate values. Ask where data is copied, materialized, serialized, decoded, and retained. Sometimes the largest optimization is not changing the calculation, but keeping the calculation close to the data.

3. Multiplicity: How many times does the work happen?

A moderately expensive operation performed once may be harmless. The same operation performed inside a loop, during every render, for every user, or on every keystroke can become the system’s defining cost.

Multiplicity is where caching, memoization, batching, indexing, and incremental computation become powerful. But each introduces a responsibility: the cached result must remain valid. A faster answer that is stale, incorrectly scoped, or expensive to invalidate is not a successful optimization.

Together, these questions provide a compact diagnostic model. Meaning prevents unnecessary work. Movement prevents expensive transfer and copying. Multiplicity prevents repeated work. Most practical performance improvements can be understood through one or more of these lenses.

Key Takeaways

  • Separate semantic design from execution strategy. First make the intended transformation clear, then optimize its implementation when measurement shows that optimization is necessary.
  • Treat resource usage as part of a function’s contract. Make network access, allocation, blocking, mutation, and repeated computation visible rather than hiding them behind innocent looking abstractions.
  • Optimize for cost locality. Organize systems so that the origin of a performance problem can be measured and changed without destabilizing unrelated behavior.
  • Ask meaning, movement, and multiplicity. Determine whether the program does more work than necessary, moves too much data, or repeats acceptable work too often.
  • Make every optimization falsifiable. State the bottleneck, predict the improvement, change one thing, and measure against a representative workload.

The deepest connection between functional thinking and performance is not that one provides elegant code while the other provides speed. It is that both are attempts to control complexity. Functional design controls the complexity of meaning. Performance engineering controls the complexity of resource consumption.

The strongest systems control both.

A program should not merely produce the right answer. Its structure should help us understand why the answer is right, where the work occurs, and what will happen when the input grows by a factor of ten. That is the real standard of scalable software: not code that is magically fast, but code whose costs remain intelligible as its responsibilities expand.

The best optimization is not the trick that makes today’s program faster. It is the design that makes tomorrow’s bottleneck obvious.

Sources

← Back to Library

Hatch New Ideas with Glasp AI 🐣

Glasp AI allows you to hatch new ideas based on your curated content. Let's curate and create with Glasp AI :)

Start Hatching 🐣