index

LLM-Assisted Performance Optimization: Profiling and Iteration

Performance optimization has a repeatable inner loop: identify the work on a slow path, change its cost, and measure the result while preserving behavior. Coding models can participate throughout that loop. They can follow execution paths, inspect profiles, construct benchmarks, and implement candidate changes, which makes a well-defined performance objective a useful engineering task for an agent.

The leverage comes from feedback. A trace identifies where time goes; a correctness check constrains the implementation; a benchmark determines whether the candidate improved the path. Each result gives the next iteration more information than the original description of the problem.

Anthropic’s account of its claude.ai performance work describes this approach across user journeys and local benchmarks.1 The method applies more broadly because the essential components are ordinary profiling, experimentation, and software review.

The optimization objective

A useful objective begins and ends with observable application behavior. Opening a project may begin with a click and end when its records are rendered and search accepts input. Sending a message may end when the interface displays the submitted message and is ready for the next action.

These boundaries determine which work is part of the problem. A spinner marks progress, but it does not establish that the requested content is usable. Receiving a response establishes network completion, while parsing and rendering may still be on the critical path.

A concrete task definition can be expressed as:

Journey: open a project containing 10,000 records.
Start: the user activates its link.
End: visible records are rendered and search accepts input.
Behavior: preserve ordering, selection, navigation, and result counts.
Objective: reduce p95 duration within a defined memory budget.
Evidence: profiles, raw timing samples, checks, and the implementation diff.

The fixture and behavior define the work being optimized. Keeping them stable allows a sequence of candidate implementations to be compared against the same task. A correction to the benchmark itself is a separate change, with its own explanation.

The profile connects a symptom to a mechanism

Elapsed time contains both execution and waiting. CPU sampling identifies active functions. A timeline reveals sequential requests, scheduling gaps, and blocked work. Resource measurements show whether the execution is limited by CPU, memory, storage, or another service.

Brendan Gregg’s USE method organizes resource investigation around utilization, saturation, and errors.2 The distinction is useful here: an idle CPU waiting on storage presents a different optimization problem from a saturated CPU repeatedly parsing the same input.

Suppose a 500 ms operation spends 300 ms parsing, 150 ms waiting for data, and 50 ms rendering. Making parsing twice as fast reduces completion time to 350 ms, a 1.43x speedup. Eliminating all rendering work would save at most 50 ms. The phase breakdown provides an upper bound on the value of each candidate.

A measured mechanism then gives the agent a tractable task. Building an index once can replace repeated scans. Reusing a parsed representation can remove repeated decoding. Overlapping independent requests can reduce serial wait. Each proposal identifies both the work removed and the condition under which that saving should appear.

The experiment loop

reproduce the path
    -> profile its execution
    -> propose a change tied to the profile
    -> run behavioral checks
    -> repeat the benchmark
    -> inspect the result and implementation
    -> retain or revert the candidate

Small changes make this loop informative. When one candidate changes parsing, caching, and scheduling together, a gain or regression is harder to attribute. A sequence of focused changes produces an explanation for each improvement and makes later regressions easier to locate.

A useful experiment record includes failed candidates as well as successful ones:

CandidateMechanismBehavioral conditionPerformance question
Cached indexAvoid repeated scansResult IDs and order remain correctDoes lookup dominate enough to matter?
Deferred parserMove work off the opening pathContent is ready before interactionDoes the next action inherit the delay?
Larger batchAmortize fixed overheadCancellation and errors remain correctHow does the tail change?

The record preserves information about the workload. A rejected candidate may become useful at another scale, while its failure explains why it was unsuitable for the current path.

Measuring a browser journey

Browser User Timing marks provide application-defined start and end events.3 They make it possible to measure a particular interaction rather than treating all page activity as one load metric.

The end event depends on the result. Data arrival, DOM update, layout, and paint are distinct stages. An input can appear before its event handling is ready, and a framework can finish a render before the browser displays the frame. The timing boundary should correspond to the application behavior being studied.

Browser traces complement the interval with an explanation. Long tasks identify stretches where input handling competes with other main-thread work. Layout and style recalculation show how a small data update can trigger a large amount of rendering work. Network timing identifies resources that are discovered late or requested serially.

The same principle applies outside a browser. A CLI’s start-to-exit duration includes process and module initialization. A database request includes query execution and result transfer. A model request includes queueing and output generation. The boundary follows the task.

Stable proxies for a fast inner loop

Wall-clock measurements include variation from scheduling, caches, and shared resources. Counts of instructions, allocations, queries, or rendering operations can provide more stable feedback for a narrow path.

Anthropic’s article describes using local metrics and checking that improvements in those metrics translated into elapsed-time gains.1 The connection is what makes a proxy useful. Fewer instructions may still leave a memory bottleneck unchanged. Fewer queries may transfer more data. Fewer DOM mutations may require a larger replacement operation.

A proxy therefore has two roles. It gives the agent a low-noise measure while exploring, and it can become a regression check after its relationship to the user journey is established. Wall-clock and field measurements remain the connection back to the application.

Experimental variation

Warmup, caching, thermal behavior, and background load affect the comparison. Alternating baseline and candidate runs reduces the chance that a changing environment consistently favors one version. A steady-state benchmark warms the relevant JIT and caches; a cold-start benchmark measures those costs explicitly.

Individual samples preserve the shape of the result. A median describes typical behavior, while the tail exposes occasional expensive paths. A p95 estimated from twenty runs depends on roughly the slowest one or two observations, so its stability is different from a percentile estimated from thousands of requests.

Input variation is equally important. A parser improvement can depend on text encoding. A lookup improvement can depend on collection size. A cache can perform well until updates invalidate it. A second fixture with different size or structure shows whether the mechanism extends beyond the case used during optimization.

For UI changes, behavior includes keyboard navigation, selection, scroll position, and the next interaction. Deferring work can improve opening time while moving the delay to the first keystroke. Measuring the adjacent action reveals that transfer.

Different workloads expose different levers

WorkloadUseful objectiveCommon sources of cost
Web applicationTime to usable input, navigation latencyInitialization, rendering, resource discovery
CLICold start and task completionModule loading, subprocesses, repeated parsing
Database serviceTail latency at a fixed arrival rateQuery plans, round trips, serialization
Model serverGoodput under latency limitsBatching, KV storage, prefill scheduling
Data pipelineCompletion time and records per secondI/O, allocation, compression, skew

The objective leaves room for the implementation to change. A request to reduce opening time can lead to an algorithmic improvement, a cache, or a better schedule. Prescribing memoization in advance narrows the search before the profile has identified the expensive work.

Correctness checks define the allowable search space. Exact CLI output, query results, model-quality criteria, and browser interactions each establish what the faster implementation must continue to do.

Load and tail latency

An isolated request measures service cost under little contention. A deployed service also has queues. Reducing service time can improve both the request itself and the waiting time of subsequent requests. Shared caches, larger batches, and additional concurrency can change that relationship.

The Tail at Scale describes why occasional delays become significant in large services.4 A request that depends on many components can inherit the slowest of them, making tail behavior a system-level property.

Arrival-rate experiments expose this effect. Error rates and rejected requests remain part of the result, since dropping slow work can otherwise look like a latency improvement. For interactive software, slower devices reveal contention that may be almost invisible on a development machine.

From a local result to a maintained improvement

A release connects the experiment to field behavior. Comparing the same journey by build, device class, and cache state shows where the gain appears. A mismatch between local and field results identifies a difference in workload or critical path that the next experiment can address.

Once a metric is stable and correlated with the application, it can protect the improvement in CI. The threshold represents an observed property of the implementation, with enough tolerance for the measurement method. The profile and experiment record explain the reason for the threshold.

The agent’s contribution is the speed of the loop: more candidate explanations can be investigated, implemented, and measured. The quality of the outcome comes from the objective and the feedback. Together they turn a vague report of slowness into a set of specific, maintainable changes.

References

Footnotes

  1. Raymond Wang, Sam Attard, and Issac G., How we made claude.ai 3x faster in two weeks, September 23, 2026. Added in the September 25 revision. ↩ ↩2

  2. Brendan Gregg, The USE Method. Resource utilization, saturation, and errors. ↩

  3. MDN, Performance.mark(). Application-defined timing markers. ↩

  4. Jeffrey Dean and Luiz André Barroso, The Tail at Scale, Communications of the ACM, 2013. Tail latency in large services. ↩

Change one variable around a fixed workload

A useful tuning loop distinguishes a configuration change from a different experiment.

  1. Baseline

    Freeze the model revision, prompt set, output length, and quality checks.

  2. Profile

    Separate loading, prefill, decode, and scheduling costs.

  3. Candidate

    Change the setting that addresses the observed bottleneck.

  4. Accept or revert

    Compare repeated runs and retain the change only if it meets the objective.

A faster run is evidence only when the workload and correctness conditions remain comparable.

Check the variables that can imitate a speedup

These changes can matter, but they must be named as changes to the experiment.

CaseApparent improvementConfounding change
Lower first-token timeA prefix was reusedCompare cache state explicitly
Higher tokens per secondThe output became shorter or easierHold the token budget and workload fixed
Lower memory usePrecision or context was reducedRepeat quality and target-context validation
Better aggregate throughputConcurrency increasedCheck per-request latency and deadlines

Report the configuration and workload with the result, rather than attributing every gain to the last parameter edited.