<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE rfc [
  <!ENTITY nbsp "&#160;">
  <!ENTITY zwsp "&#8203;">
  <!ENTITY nbhy "&#8209;">
  <!ENTITY wj "&#8288;">
]>
<?xml-stylesheet type="text/xsl" href="rfc2629.xslt"?>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude"
     category="info"
     docName="draft-gaikwad-llm-benchmarking-profiles-00"
     ipr="trust200902"
     obsoletes=""
     updates=""
     submissionType="IETF"
     xml:lang="en"
     version="3">

  <front>
    <title abbrev="LLM Benchmarking Profiles">Performance Benchmarking Profiles for Large Language Model Serving Systems</title>
    
    <seriesInfo name="Internet-Draft" value="draft-gaikwad-llm-benchmarking-profiles-00"/>
    
    <author fullname="Madhava Gaikwad" initials="M." surname="Gaikwad">
      <organization>Independent Researcher</organization>
      <address>
        <email>gaikwad.madhav@gmail.com</email>
      </address>
    </author>
    
    <date year="2026" month="January"/>
    
    <area>General</area>
    <workgroup>Network Working Group</workgroup>
    
    <keyword>LLM</keyword>
    <keyword>benchmarking</keyword>
    <keyword>performance</keyword>
    <keyword>inference</keyword>
    <keyword>AI</keyword>
    
    <abstract>
      <t>This document defines performance benchmarking profiles for Large Language Model (LLM) serving systems. Profiles bind the terminology defined in draft-gaikwad-llm-benchmarking-terminology and the procedures described in draft-gaikwad-llm-benchmarking-methodology to concrete architectural roles and workload patterns. Each profile clarifies the System Under Test (SUT) boundary, measurement points, and interpretation constraints required for reproducible and comparable benchmarking.</t>
      <t>This document specifies profiles only. It does not define new metrics, benchmark workloads, or acceptance thresholds.</t>
    </abstract>
  </front>

  <middle>
    <section anchor="introduction">
      <name>Introduction</name>
      <t>LLM serving systems are rarely monolithic. Production deployments typically compose multiple infrastructural intermediaries before a request reaches a Model Engine. A request may pass through an API gateway for authentication, an AI firewall for prompt inspection, a load balancer for routing, and finally arrive at an inference engine. Each component adds latency and affects throughput.</t>
      
      <t>Performance metrics such as Time to First Token (TTFT) or throughput are boundary dependent. A TTFT measurement taken at the client includes network latency, gateway processing, firewall inspection, queue wait time, and prefill computation. The same measurement taken at the engine boundary includes only queue wait and prefill. Without explicit boundary declaration, reported results cannot be compared.</t>
      
      <t>This document addresses this ambiguity by defining benchmarking profiles: standardized descriptions of SUT boundaries and their associated performance interpretation rules. <xref target="infrastructure-profiles"/> defines four infrastructure profiles that specify what component is being measured. <xref target="workload-profiles"/> defines workload profiles that specify how that component is tested. <xref target="delta-measurement"/> then shows how to attribute latency across composed systems using delta measurement.</t>

      <figure anchor="fig-stack">
        <name>Typical LLM Serving Stack</name>
        <artwork type="ascii-art"><![CDATA[
                Client
                  |
                  v
        +------------------+
        |   AI Gateway     |<-- Auth, routing, caching
        +--------+---------+
                 |
                 v
        +------------------+
        |   AI Firewall    |<-- Prompt inspection
        +--------+---------+
                 |
                 v
        +------------------+
        |  Model Engine    |<-- Inference
        +--------+---------+
                 |
                 v
        +------------------+
        |   AI Firewall    |<-- Output inspection
        +--------+---------+
                 |
                 v
        +------------------+
        |   AI Gateway     |<-- Response normalization
        +--------+---------+
                 |
                 v
               Client

Each layer adds latency. Benchmarks must declare which layers are included.
        ]]></artwork>
      </figure>

      <section anchor="terminology-alignment">
        <name>Terminology Alignment</name>
        <t>This document uses metrics defined in <xref target="I-D.gaikwad-llm-benchmarking-terminology"/>. The following table maps profile-specific terms to their normative definitions.</t>
        
        <table anchor="term-mapping">
          <name>Terminology Mapping</name>
          <thead>
            <tr>
              <th>Term Used in Profiles</th>
              <th>Terminology Draft Reference</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>TTFT</td><td>Time to First Token</td></tr>
            <tr><td>ITL</td><td>Inter-Token Latency</td></tr>
            <tr><td>TPOT</td><td>Time per Output Token</td></tr>
            <tr><td>Queue Residence Time</td><td>Queue Wait Time</td></tr>
            <tr><td>FRR</td><td>False Refusal Rate</td></tr>
            <tr><td>Guardrail Overhead</td><td>Guardrail Processing Overhead</td></tr>
            <tr><td>Task Completion Latency</td><td>Task Completion Latency</td></tr>
            <tr><td>Goodput</td><td>Goodput</td></tr>
          </tbody>
        </table>
      </section>
    </section>

    <section anchor="requirements">
      <name>Requirements Language</name>
      <t>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they appear in all capitals, as shown here.</t>
    </section>

    <section anchor="taxonomy">
      <name>Profile Taxonomy</name>
      <t>Profiles divide into two categories that serve orthogonal purposes. Conflating them produces misleading benchmarks.</t>
      
      <section anchor="infrastructure-profile-types">
        <name>Infrastructure Profiles</name>
        <t>Infrastructure Profiles define what is being tested. They specify the SUT boundary: where measurements start and end, what components are included, and what is excluded.</t>
        
        <table anchor="infra-profiles">
          <name>Infrastructure Profiles</name>
          <thead>
            <tr>
              <th>Profile</th>
              <th>SUT Boundary</th>
              <th>Primary Question Answered</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>Model Engine</td><td>Inference runtime only</td><td>How fast can this engine generate tokens?</td></tr>
            <tr><td>AI Gateway</td><td>API intermediary layer</td><td>What overhead does the gateway add?</td></tr>
            <tr><td>AI Firewall</td><td>Security inspection layer</td><td>What latency and accuracy does inspection cost?</td></tr>
            <tr><td>Compound System</td><td>End-to-end orchestration</td><td>How long does it take to complete a task?</td></tr>
          </tbody>
        </table>
        
        <t>The choice of infrastructure profile determines which metrics are meaningful. Measuring "AI Firewall throughput" in tokens per second conflates firewall performance with downstream engine performance. The firewall does not generate tokens; it inspects them. Appropriate firewall metrics include inspection latency, detection rate, and false positive rate.</t>
      </section>
      
      <section anchor="workload-profile-types">
        <name>Workload Profiles</name>
        <t>Workload Profiles define how the SUT is tested. They specify traffic patterns, request characteristics, and arrival models. Workload profiles are independent of infrastructure profiles.</t>
        
        <table anchor="workload-profiles-table">
          <name>Workload Profiles</name>
          <thead>
            <tr>
              <th>Profile</th>
              <th>Traffic Pattern</th>
              <th>Applicable To</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>Chatbot Workload</td><td>Multi-turn, streaming, human-paced</td><td>Engine, Gateway, Firewall, Compound</td></tr>
            <tr><td>Compound Workflow</td><td>Multi-step, tool-using, machine-paced</td><td>Compound System primarily</td></tr>
          </tbody>
        </table>
        
        <t>A Chatbot Workload can be applied to a Model Engine (measuring raw inference speed), an AI Gateway (measuring gateway overhead under conversational traffic), or a Compound System (measuring end-to-end chat latency including retrieval). The infrastructure profile determines the measurement boundary; the workload profile determines the traffic shape.</t>
        
        <t>Conflating infrastructure and workload profiles produces non-comparable results. "Chatbot benchmark on Gateway A" versus "Chatbot benchmark on Engine B" compares different things. The former includes gateway overhead; the latter does not. Valid comparison requires either:</t>
        <ul>
          <li>Same infrastructure profile, different implementations (Gateway A vs Gateway B)</li>
          <li>Same implementation, different workload profiles (Chatbot vs Compound Workflow on Engine A)</li>
        </ul>
        <t>Cross-profile comparisons require explicit delta decomposition (<xref target="delta-measurement"/>).</t>
      </section>
      
      <section anchor="profile-selection">
        <name>Profile Selection Guidance</name>
        <table anchor="selection-guide">
          <name>Profile Selection Guide</name>
          <thead>
            <tr>
              <th>If you want to measure...</th>
              <th>Use Infrastructure Profile</th>
              <th>Apply Workload Profile</th>
            </tr>
          </thead>
          <tbody>
            <tr><td>Raw model inference speed</td><td>Model Engine</td><td>Chatbot or synthetic</td></tr>
            <tr><td>Gateway routing overhead</td><td>AI Gateway</td><td>Match production traffic</td></tr>
            <tr><td>Security inspection cost</td><td>AI Firewall</td><td>Mixed benign/adversarial</td></tr>
            <tr><td>End-to-end agent latency</td><td>Compound System</td><td>Compound Workflow</td></tr>
            <tr><td>Full-stack production performance</td><td>Composite (see <xref target="composition"/>)</td><td>Match production traffic</td></tr>
          </tbody>
        </table>
      </section>
    </section>

    <section anchor="infrastructure-profiles">
      <name>Infrastructure Profiles</name>
      
      <section anchor="model-engine">
        <name>Model Engine Profile</name>
        
        <section anchor="engine-definition">
          <name>Definition and Concepts</name>
          <t>A Model Engine is the runtime responsible for executing LLM inference. Before specifying the benchmark boundary, understanding three core operations is necessary:</t>
          
          <t><strong>Prefill</strong> (also called prompt processing): The engine processes all input tokens in parallel to build initial hidden states. Prefill is compute-bound and benefits from parallelism. Prefill latency scales with input length but can be reduced by adding more compute.</t>
          
          <t><strong>Decode</strong> (also called autoregressive generation): The engine generates output tokens one at a time, each depending on all previous tokens. Decode is memory-bandwidth-bound because each token requires reading the full model weights. Decode latency per token is relatively constant regardless of batch size, but throughput increases with batching.</t>
          
          <t><strong>KV Cache</strong>: To avoid recomputing attention over previous tokens, the engine stores key-value pairs from prior tokens. The KV cache grows with sequence length and consumes GPU memory. Cache management (allocation, eviction, swapping to CPU) directly affects how many concurrent sequences the engine can handle.</t>
          
          <t>These three operations determine the fundamental performance characteristics:</t>
          <ul>
            <li>TTFT depends primarily on prefill time plus any queue wait</li>
            <li>ITL depends on decode time per token</li>
            <li>Maximum concurrency depends on KV cache capacity</li>
            <li>Throughput depends on batching efficiency during decode</li>
          </ul>
        </section>
        
        <section anchor="engine-boundary">
          <name>Boundary Specification</name>
          <t>Included in SUT:</t>
          <ul>
            <li>Model weights and inference kernels</li>
            <li>Prefill and decode computation</li>
            <li>Batch formation and scheduling logic</li>
            <li>KV cache allocation, eviction, and swapping</li>
            <li>Speculative decoding (if enabled)</li>
            <li>Quantization and precision handling</li>
          </ul>
          
          <t>Excluded from SUT:</t>
          <ul>
            <li>Network transport beyond local interface</li>
            <li>Authentication and authorization</li>
            <li>Policy enforcement and content inspection</li>
            <li>Request routing between multiple engines</li>
            <li>Protocol translation (handled by gateway)</li>
          </ul>
        </section>
        
        <section anchor="engine-architectures">
          <name>Architecture Variants</name>
          <t>Model Engines exist in several architectural configurations that affect measurement interpretation.</t>
          
          <section anchor="monolithic">
            <name>Monolithic Architecture</name>
            <t>Prefill and decode execute on the same hardware. This is the simplest configuration and the most common in single-GPU deployments.</t>
            
            <figure anchor="fig-monolithic">
              <name>Monolithic Engine Architecture</name>
              <artwork type="ascii-art"><![CDATA[
            MONOLITHIC ENGINE

+------------------------------------------+
|               GPU / Accelerator          |
|                                          |
|  Request -> [Prefill] -> [Decode] -> Out |
|               |            |             |
|            KV Cache <------+             |
|                                          |
+------------------------------------------+

Timeline for single request:
|---- Queue ----|---- Prefill ----|---- Decode (N tokens) ----|
      t6             t6a -> t7            t7 -> t8
              ]]></artwork>
            </figure>
            
            <t>Timestamp mapping:</t>
            <table>
              <thead>
                <tr><th>Symbol</th><th>Event</th></tr>
              </thead>
              <tbody>
                <tr><td>t6</td><td>Request enters engine queue</td></tr>
                <tr><td>t6a</td><td>Prefill computation begins (batch slot acquired)</td></tr>
                <tr><td>t7</td><td>First output token generated</td></tr>
                <tr><td>t8</td><td>Last output token generated</td></tr>
              </tbody>
            </table>
            
            <t>Derived metrics:</t>
            <artwork><![CDATA[
Queue residence = t6a - t6
Prefill latency = t7 - t6a
Engine TTFT = t7 - t6
Generation time = t8 - t7
            ]]></artwork>
          </section>
          
          <section anchor="disaggregated">
            <name>Disaggregated Architecture</name>
            <t>Prefill and decode execute on separate hardware pools. Prefill nodes are optimized for compute throughput; decode nodes are optimized for memory bandwidth. After prefill completes, the KV cache must transfer across the network to the decode pool.</t>
            
            <t>This architecture appears in published systems including DistServe <xref target="DISTSERVE"/> and Mooncake <xref target="MOONCAKE"/>, and in open-source projects such as llm-d.</t>
            
            <figure anchor="fig-disaggregated">
              <name>Disaggregated Serving Architecture</name>
              <artwork type="ascii-art"><![CDATA[
                    DISAGGREGATED SERVING

+------------------+                      +------------------+
|  PREFILL POOL    |                      |  DECODE POOL     |
|                  |                      |                  |
|  High compute    |    KV Cache          |  High memory BW  |
|  utilization     |    Transfer          |  utilization     |
|                  |  ================>   |                  |
|  +-----------+   |   Network link       |  +-----------+   |
|  | GPU 0     |   |   (RDMA or TCP)      |  | GPU 0     |   |
|  +-----------+   |                      |  +-----------+   |
|  | GPU 1     |   |   Bottleneck at      |  | GPU 1     |   |
|  +-----------+   |   high context       |  +-----------+   |
|  | ...       |   |   lengths            |  | ...       |   |
|  +-----------+   |                      |  +-----------+   |
+------------------+                      +------------------+

Timeline:
|-- Queue --|-- Prefill --|-- KV Transfer --|-- Decode --|
     t6          t6a            t7a              t7 -> t8
              ]]></artwork>
            </figure>
            
            <t>The KV transfer phase (t7a) does not exist in monolithic deployments. This phase can become the bottleneck for long contexts.</t>
            
            <t>KV Transfer Constraint:</t>
            <t>Transfer time depends on context length and network bandwidth:</t>
            <artwork><![CDATA[
KV_transfer_time = (context_length * kv_bytes_per_token) / effective_bandwidth
            ]]></artwork>
            
            <t>Where:</t>
            <ul>
              <li>context_length = input tokens processed</li>
              <li>kv_bytes_per_token = 2 * num_layers * head_dim * num_heads * bytes_per_element</li>
              <li>effective_bandwidth = min(network_bandwidth, memory_bandwidth) * efficiency</li>
            </ul>
            
            <t>Bandwidth Saturation Threshold: The context length at which KV transfer time exceeds prefill compute time. Beyond this threshold, adding more prefill compute does not reduce TTFT.</t>
            
            <figure anchor="fig-kv-example">
              <name>KV Transfer Example Calculation</name>
              <artwork><![CDATA[
Configuration:
  Model: 70B parameters
  KV cache: 80 layers, 128 heads, 128 dim, BF16
  KV bytes per token: 2 * 80 * 128 * 128 * 2 = 5.24 MB
  Inter-pool bandwidth: 400 Gbps = 50 GB/s effective

At 4K context:
  KV transfer = 4096 * 5.24 MB / 50 GB/s = 430 ms

At 32K context:
  KV transfer = 32768 * 5.24 MB / 50 GB/s = 3.44 s

If prefill compute takes 500ms for 32K tokens:
  Bottleneck shifts to KV transfer at ~4.8K tokens
              ]]></artwork>
            </figure>
            
            <t>Testers benchmarking disaggregated architectures MUST report:</t>
            <table>
              <thead>
                <tr><th>Parameter</th><th>Description</th></tr>
              </thead>
              <tbody>
                <tr><td>Pool configuration</td><td>Number and type of prefill vs decode accelerators</td></tr>
                <tr><td>KV transfer mechanism</td><td>RDMA, TCP, or other; theoretical bandwidth</td></tr>
                <tr><td>KV bytes per token</td><td>Calculated from model architecture</td></tr>
                <tr><td>Observed transfer latency</td><td>Measured, not calculated</td></tr>
                <tr><td>Bandwidth saturation threshold</td><td>Context length where transfer becomes bottleneck</td></tr>
                <tr><td>TTFT boundary</td><td>Whether reported TTFT includes KV transfer</td></tr>
              </tbody>
            </table>
            
            <t>Results from disaggregated and monolithic deployments MUST NOT be directly compared without explicit architectural notation.</t>
            
            <figure anchor="fig-comparison">
              <name>Monolithic vs Disaggregated Comparison</name>
              <artwork type="ascii-art"><![CDATA[
        MONOLITHIC                         DISAGGREGATED

+----------------------+      +-----------+    +-----------+
|     Single Pool      |      |  Prefill  |    |  Decode   |
|                      |      |   Pool    |    |   Pool    |
|  Prefill --> Decode  |      |           |    |           |
|      |         |     |      | +-------+ |    | +-------+ |
|      +> KV Cache <---+      | | GPU 0 | |    | | GPU 0 | |
|                      |      | +-------+ |    | +-------+ |
|  Same memory space   |      | +-------+ |    | +-------+ |
|  No transfer needed  |      | | GPU 1 |======>| GPU 1 | |
|                      |      | +-------+ |    | +-------+ |
+----------------------+      |   KV transfer  |           |
                              +-----------+    +-----------+

TTFT = Queue + Prefill        TTFT = Queue + Prefill + KV_Transfer

Best for:                     Best for:
- Smaller models              - Large models (70B+)
- Lower latency               - Higher throughput
- Simpler deployment          - Independent scaling
              ]]></artwork>
            </figure>
          </section>
          
          <section anchor="distributed">
            <name>Distributed Architecture</name>
            <t>Model sharded across multiple accelerators using tensor parallelism (TP), pipeline parallelism (PP), or expert parallelism (EP for mixture-of-experts models).</t>
            
            <t>Testers MUST report:</t>
            <ul>
              <li>Parallelism strategy and degree (e.g., TP=8, PP=2)</li>
              <li>Interconnect type (NVLink, PCIe, InfiniBand)</li>
              <li>Collective communication overhead if measurable</li>
            </ul>
          </section>
        </section>
        
        <section anchor="engine-config">
          <name>Configuration Disclosure</name>
          <t>Testers MUST disclose:</t>
          <table>
            <thead>
              <tr><th>Configuration</th><th>Example Values</th><th>Why It Matters</th></tr>
            </thead>
            <tbody>
              <tr><td>Model precision</td><td>FP16, BF16, INT8, FP8</td><td>Affects throughput, memory, and quality</td></tr>
              <tr><td>Quantization method</td><td>GPTQ, AWQ, SmoothQuant</td><td>Different speed/quality tradeoffs</td></tr>
              <tr><td>Batch strategy</td><td>Static, continuous, chunked prefill</td><td>Affects latency distribution</td></tr>
              <tr><td>Max batch size</td><td>64 requests</td><td>Limits concurrency</td></tr>
              <tr><td>Max sequence length</td><td>8192 tokens</td><td>Limits context window</td></tr>
              <tr><td>KV cache memory</td><td>24 GB</td><td>Limits concurrent sequences</td></tr>
            </tbody>
          </table>
          
          <section anchor="speculative">
            <name>Speculative Decoding</name>
            <t>Speculative decoding uses a smaller draft model to propose multiple tokens, then verifies them in parallel with the target model. When draft tokens are accepted, generation is faster. When rejected, compute is wasted.</t>
            
            <t>If speculative decoding is enabled, testers MUST report:</t>
            <table>
              <thead>
                <tr><th>Parameter</th><th>Description</th></tr>
              </thead>
              <tbody>
                <tr><td>Draft model</td><td>Identifier and parameter count</td></tr>
                <tr><td>Speculation window (k)</td><td>Tokens proposed per verification step</td></tr>
                <tr><td>Acceptance rate</td><td>Fraction of draft tokens accepted</td></tr>
                <tr><td>Verification overhead</td><td>Latency when draft tokens are rejected</td></tr>
              </tbody>
            </table>
            
            <t>Acceptance rate directly affects efficiency:</t>
            <artwork><![CDATA[
High acceptance (80%), k=5:
  Expected accepted per step = 4 tokens
  Verification passes per output token = 0.25

Low acceptance (30%), k=5:
  Expected accepted per step = 1.5 tokens
  Verification passes per output token = 0.67

Result: 2.7x more verification overhead at low acceptance
            ]]></artwork>
            
            <t>Results with speculative decoding MUST be labeled separately and include observed acceptance rate.</t>
          </section>
          
          <section anchor="chunked-prefill">
            <name>Chunked Prefill</name>
            <t>Chunked prefill splits long prompts into smaller pieces, processing each chunk and potentially interleaving with decode iterations from other requests. This reduces head-of-line blocking but increases total prefill time for the chunked request.</t>
            
            <t>If chunked prefill is enabled, testers MUST report:</t>
            <ul>
              <li>Chunk size in tokens</li>
              <li>Whether chunks interleave with other requests</li>
              <li>Impact on TTFT for long prompts</li>
            </ul>
          </section>
        </section>
        
        <section anchor="engine-metrics">
          <name>Primary Metrics</name>
          <t>From <xref target="I-D.gaikwad-llm-benchmarking-terminology"/>:</t>
          <ul>
            <li>Time to First Token (TTFT)</li>
            <li>Inter-Token Latency (ITL)</li>
            <li>Time per Output Token (TPOT)</li>
            <li>Output Token Throughput</li>
          </ul>
        </section>
        
        <section anchor="engine-secondary">
          <name>Secondary Metrics</name>
          <ul>
            <li>Request Throughput</li>
            <li>Queue Depth over time</li>
            <li>Queue Residence Time</li>
            <li>Prefill Latency (TTFT minus queue residence)</li>
            <li>Batch Utilization</li>
          </ul>
        </section>
        
        <section anchor="engine-constraints">
          <name>Benchmarking Constraints</name>
          <t>Request rate saturation differs from token saturation. A system might handle 2000 output tokens per second but only 50 requests per second if scheduling overhead dominates. Testers SHOULD measure both dimensions.</t>
          
          <t>Mixed-length workloads increase tail latency under continuous batching. Short requests arriving behind long prefills experience head-of-line blocking. When workload includes high length variance, measure fairness: the ratio of actual latency to expected latency based on request size.</t>
        </section>
      </section>

      <section anchor="ai-gateway">
        <name>AI Gateway Profile</name>
        
        <section anchor="gateway-definition">
          <name>Definition and Concepts</name>
          <t>An AI Gateway is a network-facing intermediary that virtualizes access to one or more Model Engines. Gateways handle cross-cutting concerns that do not belong in the inference engine itself.</t>
          
          <t>Gateways perform several functions that affect latency:</t>
          
          <t><strong>Request Processing:</strong> TLS termination, authentication, schema validation, and protocol translation. These operations add fixed overhead per request.</t>
          
          <t><strong>Routing:</strong> Selection of backend engine based on load, capability, or policy. Intelligent routing (e.g., KV-cache-aware) adds decision latency but may reduce overall latency by improving cache hit rates.</t>
          
          <t><strong>Caching:</strong> Gateways may implement response caching. Traditional exact-match caching has limited utility for LLM traffic due to low query repetition. Semantic caching (matching similar queries) improves hit rates but introduces quality risk from approximate matches.</t>
          
          <t><strong>Admission Control:</strong> Rate limiting and quota enforcement. Under load, admission control adds queuing delay or rejects requests.</t>
        </section>
        
        <section anchor="gateway-boundary">
          <name>Boundary Specification</name>
          <t>Included in SUT:</t>
          <ul>
            <li>TLS termination</li>
            <li>Authentication and authorization</li>
            <li>Schema validation and protocol translation</li>
            <li>Load balancing across engines or model replicas</li>
            <li>Semantic cache lookup and population</li>
            <li>Admission control and rate limiting</li>
            <li>Retry and fallback logic</li>
            <li>Response normalization</li>
          </ul>
          
          <t>Excluded from SUT:</t>
          <ul>
            <li>Model inference computation (handled by downstream engine)</li>
            <li>Content inspection for safety (handled by AI Firewall)</li>
          </ul>
        </section>
        
        <section anchor="gateway-baseline">
          <name>Baseline Requirement</name>
          <t>Gateway overhead is meaningful only relative to direct engine access. Gateway benchmarks MUST declare measurement type:</t>
          <table>
            <thead>
              <tr><th>Measurement Type</th><th>What It Includes</th></tr>
            </thead>
            <tbody>
              <tr><td>Aggregate</td><td>Gateway processing plus downstream engine latency</td></tr>
              <tr><td>Differential</td><td>Gateway overhead only, relative to direct engine access</td></tr>
            </tbody>
          </table>
          
          <t>To measure differential latency:</t>
          <ol>
            <li>Benchmark the Model Engine directly (baseline)</li>
            <li>Benchmark through the Gateway to the same engine (same workload, same conditions)</li>
            <li>Compute delta: Gateway_overhead = Gateway_TTFT - Engine_TTFT</li>
          </ol>
          <t>Report both absolute values and delta.</t>
        </section>
        
        <section anchor="gateway-lb">
          <name>Load Balancing Disclosure</name>
          <t>Load balancing strategy affects tail latency. Testers MUST report:</t>
          <table>
            <thead>
              <tr><th>Configuration</th><th>Options</th><th>Impact</th></tr>
            </thead>
            <tbody>
              <tr><td>Algorithm</td><td>Round-robin, least-connections, weighted, adaptive</td><td>Tail latency variance</td></tr>
              <tr><td>Health checks</td><td>Interval, timeout, failure threshold</td><td>Failover speed</td></tr>
              <tr><td>Sticky sessions</td><td>Enabled/disabled, key type</td><td>Cache locality</td></tr>
              <tr><td>Retry policy</td><td>Max retries, backoff strategy</td><td>Failure handling</td></tr>
            </tbody>
          </table>
          
          <t>For intelligent routing (KV-cache-aware, cost-optimized, latency-optimized):</t>
          <ul>
            <li>Routing signals used (queue depth, cache locality, model cost)</li>
            <li>Decision latency overhead</li>
            <li>Routing effectiveness (e.g., cache hit improvement from routing)</li>
          </ul>
        </section>
        
        <section anchor="gateway-multimodel">
          <name>Multi-Model Gateway</name>
          <t>Modern gateways route to multiple backend models based on capability, cost, or latency.</t>
          
          <t>When gateway routes to heterogeneous backends, testers MUST report:</t>
          <ul>
            <li>Model selection logic: Rule-based, cost-optimized, capability-based</li>
            <li>Backend composition: List of models and their roles</li>
            <li>Fallback behavior: Conditions triggering model switching</li>
          </ul>
          
          <t>Per-model metrics SHOULD be reported separately.</t>
          
          <t>Cross-gateway comparison requires backend normalization. Comparing Gateway A (routing to GPT-4) against Gateway B (routing to Llama-70B) conflates gateway performance with model performance.</t>
        </section>
        
        <section anchor="semantic-cache">
          <name>Semantic Cache</name>
          <t>Semantic caching matches queries by meaning rather than exact text. A cache hit on "What is the capital of France?" might serve a response cached from "France's capital city?" This improves hit rates but risks serving inappropriate responses for queries that are similar but not equivalent.</t>
          
          <t>Configuration Disclosure:</t>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Example</th><th>Why It Matters</th></tr>
            </thead>
            <tbody>
              <tr><td>Similarity threshold</td><td>Cosine >= 0.92</td><td>Lower threshold: more hits, more mismatches</td></tr>
              <tr><td>Embedding model</td><td>text-embedding-3-small</td><td>Affects similarity quality</td></tr>
              <tr><td>Cache capacity</td><td>100,000 entries</td><td>Hit rate ceiling</td></tr>
              <tr><td>Eviction policy</td><td>LRU, frequency-based</td><td>Long-term hit rate</td></tr>
              <tr><td>Cache scope</td><td>Global, per-tenant, per-user</td><td>Security and hit rate tradeoff</td></tr>
              <tr><td>TTL</td><td>1 hour</td><td>Staleness vs hit rate</td></tr>
            </tbody>
          </table>
          
          <t>Required Metrics:</t>
          <table>
            <thead>
              <tr><th>Metric</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Hit rate</td><td>Fraction of requests served from cache</td></tr>
              <tr><td>Hit rate distribution</td><td>P50, P95, P99 of per-session hit rates</td></tr>
              <tr><td>Latency on hit</td><td>TTFT when cache serves response</td></tr>
              <tr><td>Latency on miss</td><td>TTFT when engine generates</td></tr>
              <tr><td>Cache delta</td><td>Latency_miss minus Latency_hit</td></tr>
              <tr><td>Mismatch rate</td><td>Fraction of hits where cached response was inappropriate</td></tr>
            </tbody>
          </table>
          
          <t>Mismatch rate requires evaluation. Testers SHOULD disclose evaluation methodology (human review, automated comparison, or LLM-as-judge).</t>
          
          <t>Session Definition: For per-session metrics, define what constitutes a session: requests sharing a session identifier, requests from the same user within a time window, or another definition. Testers MUST disclose session definition.</t>
          
          <t>Staleness in RAG Systems: When semantic cache operates with a RAG system, cached responses may reference documents that have since been updated.</t>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Description</th></tr>
            </thead>
            <tbody>
              <tr><td>Index update frequency</td><td>How often RAG index refreshes</td></tr>
              <tr><td>Cache TTL</td><td>Maximum age of cached entries</td></tr>
              <tr><td>Staleness risk</td><td>Estimated fraction of stale cache hits</td></tr>
            </tbody>
          </table>
          
          <t>Staleness risk estimate:</t>
          <artwork><![CDATA[
staleness_risk = (average_cache_age / index_update_interval) * corpus_change_rate
          ]]></artwork>
          
          <t>Benchmarking Constraints: Workload diversity determines hit rate. Testers MUST report:</t>
          <ul>
            <li>Number of distinct query clusters in workload</li>
            <li>Cache state at test start (cold or warm)</li>
            <li>Time until hit rate stabilizes</li>
          </ul>
        </section>
      </section>

      <section anchor="ai-firewall">
        <name>AI Firewall Profile</name>
        
        <section anchor="firewall-definition">
          <name>Definition and Concepts</name>
          <t>An AI Firewall is a bidirectional security intermediary that inspects LLM inputs and outputs to detect and prevent policy violations.</t>
          
          <t>Unlike traditional firewalls that examine packet headers or match byte patterns, AI Firewalls analyze semantic content. They must understand what a prompt is asking and what a response is saying. This requires ML models, making firewall latency fundamentally different from network firewall latency.</t>
          
          <t>The firewall sits on the request path and adds latency to every request. The core tradeoff: more thorough inspection catches more threats but costs more time.</t>
        </section>
        
        <section anchor="firewall-boundary">
          <name>Boundary Specification</name>
          <t>Included in SUT:</t>
          <ul>
            <li>Prompt analysis and classification</li>
            <li>Output content inspection</li>
            <li>Policy decision engine</li>
            <li>Block, allow, or modify actions</li>
          </ul>
          
          <t>Excluded from SUT:</t>
          <ul>
            <li>Model inference (upstream or downstream)</li>
            <li>Network-layer firewalling (traditional WAF)</li>
            <li>Authentication (handled by gateway)</li>
          </ul>
        </section>
        
        <section anchor="firewall-directions">
          <name>Enforcement Directions</name>
          <t>AI Firewalls operate bidirectionally. Each direction addresses different threats.</t>
          
          <t>Inbound Enforcement inspects user prompts before they reach the model:</t>
          <table>
            <thead>
              <tr><th>Threat</th><th>Description</th></tr>
            </thead>
            <tbody>
              <tr><td>Direct prompt injection</td><td>User attempts to override system instructions</td></tr>
              <tr><td>Indirect prompt injection</td><td>Malicious content in retrieved documents</td></tr>
              <tr><td>Jailbreak attempts</td><td>Techniques to bypass model safety training</td></tr>
              <tr><td>Context poisoning</td><td>Adversarial content to manipulate model behavior</td></tr>
            </tbody>
          </table>
          
          <t>Outbound Enforcement inspects model outputs before they reach the user:</t>
          <table>
            <thead>
              <tr><th>Threat</th><th>Description</th></tr>
            </thead>
            <tbody>
              <tr><td>PII leakage</td><td>Model outputs personal information</td></tr>
              <tr><td>Policy violation</td><td>Output violates content policies</td></tr>
              <tr><td>Tool misuse</td><td>Model attempts unauthorized actions</td></tr>
              <tr><td>Data exfiltration</td><td>Sensitive information encoded in output</td></tr>
            </tbody>
          </table>
          
          <t>Testers MUST declare which directions are enforced. A benchmark testing inbound-only enforcement MUST NOT claim protection against outbound threats.</t>
        </section>
        
        <section anchor="firewall-architecture">
          <name>Inspection Architecture</name>
          <t>Firewalls use different inspection strategies with distinct latency characteristics.</t>
          
          <figure anchor="fig-inspection">
            <name>Inspection Architecture Comparison</name>
            <artwork type="ascii-art"><![CDATA[
INSPECTION ARCHITECTURE COMPARISON

BUFFERED (adds to TTFT, no ITL impact):

  Input:   ================........................
           |-- collect --|-- analyze --|-- forward -->

  Output:  ..................========........
           |- engine generates -|- buffer -|- analyze -|-->
                                t7                     t12
                                |-- inspection delay --|

STREAMING (no TTFT impact, adds to ITL):

  Output:  ..o..o..o..o..o..o..o..o..o..o..o..o..o..o..o.
              |     |     |     |     |     |     |
           inspect  |  inspect  |  inspect  |  inspect
              |     |     |     |     |     |     |
           --o-----o-----o-----o-----o-----o-----o----->
           Variable delays, increased jitter
            ]]></artwork>
          </figure>
          
          <t>Buffered Inspection: The firewall collects complete input (or output) before analysis.</t>
          <t>Characteristics:</t>
          <ul>
            <li>Adds to TTFT (inbound) or delays token delivery (outbound)</li>
            <li>No impact on ITL once streaming starts</li>
            <li>Enables deep analysis requiring full context</li>
          </ul>
          
          <t>For outbound buffered inspection, the client receives the first token later than the engine generates it. This distinction matters:</t>
          <artwork><![CDATA[
Engine TTFT (t7 - t6): 200ms
Outbound inspection: 50ms
Client-observed TTFT (t12 - t0): 250ms + network
          ]]></artwork>
          
          <t>Streaming Inspection: The firewall analyzes content as tokens flow through.</t>
          <t>Characteristics:</t>
          <ul>
            <li>Adds per-token overhead to ITL</li>
            <li>May batch or pause tokens during analysis</li>
            <li>Introduces jitter in token delivery</li>
          </ul>
          
          <t>Required measurements:</t>
          <table>
            <thead>
              <tr><th>Metric</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Per-token inspection delay</td><td>Average latency added per token</td></tr>
              <tr><td>Maximum pause duration</td><td>Longest delay during streaming</td></tr>
              <tr><td>Pause frequency</td><td>How often inspection causes batching</td></tr>
              <tr><td>Jitter contribution</td><td>Standard deviation of delays</td></tr>
            </tbody>
          </table>
          
          <t>Hybrid Inspection: Initial buffering followed by streaming. Common pattern: buffer first N tokens for context, then stream with spot-checks.</t>
          <t>Configuration to disclose:</t>
          <ul>
            <li>Buffer threshold (tokens before streaming starts)</li>
            <li>Spot-check frequency</li>
            <li>Escalation triggers (patterns that switch to full buffering)</li>
          </ul>
        </section>
        
        <section anchor="firewall-metrics">
          <name>Required Metrics</name>
          <t>Accuracy Metrics:</t>
          <table>
            <thead>
              <tr><th>Metric</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Detection Rate</td><td>Fraction of malicious inputs correctly blocked</td></tr>
              <tr><td>False Positive Rate (FPR)</td><td>Fraction of benign inputs blocked by firewall</td></tr>
              <tr><td>False Refusal Rate (FRR)</td><td>Fraction of policy-compliant requests refused at system boundary</td></tr>
              <tr><td>Over-Defense Rate</td><td>FPR conditional on trigger-word presence in benign inputs</td></tr>
            </tbody>
          </table>
          
          <t>FPR vs FRR: FPR measures firewall classifier errors on a benign test set. FRR measures all refusals observed at the system boundary, which may include:</t>
          <ul>
            <li>Firewall blocks (captured in FPR)</li>
            <li>Model refusals (model's own safety behavior)</li>
            <li>Policy engine blocks (business rules)</li>
            <li>Rate limiting (capacity rejection)</li>
          </ul>
          <t>Therefore: FRR >= FPR when other refusal sources exist.</t>
          <t>When reporting both, attribute refusals by source when possible.</t>
          
          <t>Over-Defense Rate: Measures false positives on benign inputs that contain words commonly associated with attacks.</t>
          <artwork><![CDATA[
Over-Defense Rate = P(Block | Benign AND Contains_Trigger_Words)
          ]]></artwork>
          
          <t>Examples of benign inputs that may trigger over-defense:</t>
          <ul>
            <li>"Explain how prompt injection attacks work" (security education)</li>
            <li>"What does 'ignore previous instructions' mean?" (linguistic question)</li>
            <li>"How do I kill a process in Linux?" (technical query)</li>
          </ul>
          <t>The test corpus for over-defense MUST contain semantically benign inputs that happen to include trigger words. Testing with trivially benign inputs does not measure real over-defense risk.</t>
          
          <t>Latency Metrics:</t>
          <table>
            <thead>
              <tr><th>Metric</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Passing latency</td><td>Overhead when firewall allows request</td></tr>
              <tr><td>Blocking latency</td><td>Time to reach block decision</td></tr>
              <tr><td>Throughput degradation</td><td>Reduction in requests per second</td></tr>
            </tbody>
          </table>
          
          <t>Latency may vary by decision path:</t>
          <artwork><![CDATA[
Example:
  Allow (no flags): 8ms
  Allow (flagged, deep analysis): 45ms
  Block (pattern match): 3ms
  Block (semantic analysis): 67ms
          ]]></artwork>
          <t>Report latency distribution by decision type.</t>
        </section>
        
        <section anchor="firewall-workload">
          <name>Workload Specification</name>
          <t>AI Firewall benchmarks require careful workload design.</t>
          
          <t>Benign Workload: Normal traffic with no policy violations. Measures passing latency, FRR, and throughput impact on legitimate use. Source: Sanitized production samples or standard datasets.</t>
          
          <t>Adversarial Workload: Known attack patterns. Measures detection rate, blocking latency, and FPR. Source: Published datasets (BIPIA <xref target="BIPIA"/>, JailbreakBench, PromptInject) or red team generated. Do not publish working exploits.</t>
          
          <t>Mixed Workload (recommended): Combines benign and adversarial at declared ratio.</t>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Example</th></tr>
            </thead>
            <tbody>
              <tr><td>Mix ratio</td><td>95% benign, 5% adversarial</td></tr>
              <tr><td>Adversarial categories</td><td>40% injection, 30% jailbreak, 30% PII</td></tr>
              <tr><td>Arrival pattern</td><td>Uniform or bursty</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="firewall-multilayer">
          <name>Multi-Layer Firewall</name>
          <t>Production deployments often stack multiple inspection layers.</t>
          <artwork><![CDATA[
Request -> Quick Filter -> ML Classifier -> Model -> Semantic Check -> PII Scan -> Response
              |               |                        |              |
           regex           embedding               output           entity
           + rules         classifier             analysis         detection
          ]]></artwork>
          
          <t>When multiple layers exist, report:</t>
          <ul>
            <li>Number and position of layers</li>
            <li>Per-layer latency</li>
            <li>Execution model: Series (latencies add) or parallel</li>
            <li>Short-circuit behavior: Does blocking at layer N skip later layers?</li>
          </ul>
          
          <t>Delta decomposition:</t>
          <artwork><![CDATA[
Total overhead = Quick(2ms) + ML(12ms) + Semantic(34ms) + PII(8ms) = 56ms

With short-circuit on input block:
  Overhead = Quick(2ms) + ML(12ms) = 14ms
          ]]></artwork>
        </section>
        
        <section anchor="firewall-constraints">
          <name>Benchmarking Constraints</name>
          <t>Blocking speed alone is meaningless. A firewall blocking all requests in 1ms is useless. Always measure impact on benign traffic alongside detection effectiveness.</t>
          
          <t>Disclose integration with WAF, rate limiting, or DDoS protection. These add latency.</t>
          
          <t>Different attack categories have different detection latencies. Pattern-based detection is faster than semantic analysis. Report detection latency by category.</t>
        </section>
      </section>

      <section anchor="compound-system">
        <name>Compound System Profile</name>
        
        <section anchor="compound-definition">
          <name>Definition and Concepts</name>
          <t>A Compound System executes multiple inference, retrieval, and tool-use steps to satisfy a user intent. The system orchestrates these steps, manages state across them, and produces a final response.</t>
          
          <t>Examples: RAG pipelines, multi-agent systems, tool-using assistants, coding agents.</t>
          
          <t>Unlike single-inference benchmarks, compound system benchmarks measure task completion, not token generation. The primary question is "Did it accomplish the goal?" not "How fast did it generate tokens?"</t>
        </section>
        
        <section anchor="compound-boundary">
          <name>Boundary Specification</name>
          <t>Included in SUT:</t>
          <ul>
            <li>Orchestration and planning logic</li>
            <li>Multiple LLM inference calls</li>
            <li>Retrieval pipeline (embedding, search, reranking)</li>
            <li>Tool execution environment</li>
            <li>Conversation state management</li>
            <li>Agent-to-agent communication</li>
          </ul>
          
          <t>Excluded from SUT:</t>
          <ul>
            <li>External APIs outside the system boundary (latency measured but not controlled)</li>
            <li>User interface rendering</li>
            <li>Arbitrary user-supplied code</li>
          </ul>
          
          <t>Boundary Rule: The Compound System boundary includes only components deployed and controlled as part of the serving system. User-provided plugins or custom code at runtime are excluded. This prevents ambiguity when comparing systems with different extensibility models.</t>
          
          <table>
            <thead>
              <tr><th>Component</th><th>Included?</th><th>Rationale</th></tr>
            </thead>
            <tbody>
              <tr><td>Built-in retrieval</td><td>Yes</td><td>Part of serving system</td></tr>
              <tr><td>Standard tool library</td><td>Yes</td><td>Shipped with system</td></tr>
              <tr><td>User-uploaded plugin</td><td>No</td><td>User-supplied</td></tr>
              <tr><td>External API (weather)</td><td>Latency measured</td><td>Outside boundary</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="compound-metrics">
          <name>Primary Metrics</name>
          <table>
            <thead>
              <tr><th>Metric</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Task Completion Latency</td><td>Time from user request to final response</td></tr>
              <tr><td>Task Success Rate</td><td>Fraction of tasks completed correctly</td></tr>
            </tbody>
          </table>
          
          <t>Task Success has two dimensions:</t>
          <table>
            <thead>
              <tr><th>Type</th><th>Definition</th><th>Evaluation</th></tr>
            </thead>
            <tbody>
              <tr><td>Hard Success</td><td>Structural correctness</td><td>Automated (valid JSON, no errors)</td></tr>
              <tr><td>Soft Success</td><td>Semantic correctness</td><td>Requires evaluation</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="compound-oracle">
          <name>Evaluation Oracle</name>
          <t>When using automated evaluation for Task Success Rate, disclose oracle methodology.</t>
          
          <t>LLM-as-Judge:</t>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Report</th></tr>
            </thead>
            <tbody>
              <tr><td>Judge model</td><td>Identifier and version</td></tr>
              <tr><td>Judge prompt</td><td>Full prompt or published rubric reference</td></tr>
              <tr><td>Ground truth access</td><td>Whether judge sees reference answers</td></tr>
              <tr><td>Sampling</td><td>Temperature, judgments per task</td></tr>
            </tbody>
          </table>
          <t>Report inter-rater agreement if using multiple judges.</t>
          
          <t>Rule-Based Evaluation:</t>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Report</th></tr>
            </thead>
            <tbody>
              <tr><td>Rule specification</td><td>Formal definition</td></tr>
              <tr><td>Coverage</td><td>Fraction of criteria that are rule-checkable</td></tr>
              <tr><td>Edge case handling</td><td>How ambiguous cases resolve</td></tr>
            </tbody>
          </table>
          
          <t>Human Evaluation:</t>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Report</th></tr>
            </thead>
            <tbody>
              <tr><td>Evaluator count</td><td>Number of humans</td></tr>
              <tr><td>Rubric</td><td>Criteria and scoring</td></tr>
              <tr><td>Agreement</td><td>Inter-rater reliability (e.g., Cohen's Kappa)</td></tr>
              <tr><td>Blinding</td><td>Whether evaluators knew system identity</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="compound-secondary">
          <name>Secondary Metrics</name>
          <table>
            <thead>
              <tr><th>Metric</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Trace Depth</td><td>Sequential steps in execution</td></tr>
              <tr><td>Fan-out Factor</td><td>Maximum parallel sub-requests</td></tr>
              <tr><td>Sub-Request Count</td><td>Total LLM calls per user request</td></tr>
              <tr><td>Loop Incidence Rate</td><td>Fraction of tasks with repetitive non-progressing actions</td></tr>
              <tr><td>Stalled Task Rate</td><td>Fraction of tasks hitting step limit without resolution</td></tr>
              <tr><td>State Management Overhead</td><td>Latency and memory for multi-turn context</td></tr>
            </tbody>
          </table>
          
          <t>Stalled Task Rate:</t>
          <artwork><![CDATA[
Stalled Task Rate = Tasks_reaching_max_steps / Total_tasks
          ]]></artwork>
          <t>Stalled tasks differ from loops. A loop repeats similar actions. A stalled task may try diverse actions but fail to converge. Both indicate problems but different ones.</t>
        </section>
        
        <section anchor="rag-subprofile">
          <name>RAG Sub-Profile</name>
          <t>When Compound System includes Retrieval-Augmented Generation:</t>
          
          <figure anchor="fig-rag">
            <name>RAG Pipeline Latency</name>
            <artwork type="ascii-art"><![CDATA[
                        RAG PIPELINE LATENCY

    Query --> Embed --> Search --> Rerank --> Inject --> Generate
      |         |          |          |          |          |
      Q         E          S          R          I          G
      |         |          |          |          |          |
    ----------------------------------------------------------->
    0ms      15ms       60ms       180ms      185ms      385ms
              |          |          |          |          |
              +--15ms----+          |          |          |
                   +-----45ms-------+          |          |
                              +-----120ms------+          |
                                        +--5ms-+          |
                                              +--200ms----+

    TTFT = E + S + R + I + Prefill + Queue = 385ms
            ]]></artwork>
          </figure>
          
          <t>Configuration Disclosure:</t>
          <table>
            <thead>
              <tr><th>Component</th><th>Parameters</th></tr>
            </thead>
            <tbody>
              <tr><td>Embedding</td><td>Model, dimensions, batch size</td></tr>
              <tr><td>Vector store</td><td>Type, index configuration</td></tr>
              <tr><td>Search</td><td>Top-k, similarity metric, filters</td></tr>
              <tr><td>Reranking</td><td>Model (if used), top-n after rerank</td></tr>
              <tr><td>Context</td><td>Max tokens, formatting template</td></tr>
            </tbody>
          </table>
          
          <t>RAG-Specific Metrics:</t>
          <table>
            <thead>
              <tr><th>Metric</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Embedding Latency</td><td>Query to vector conversion</td></tr>
              <tr><td>Retrieval Latency</td><td>Search and fetch time</td></tr>
              <tr><td>Retrieval Recall</td><td>Fraction of relevant docs retrieved</td></tr>
              <tr><td>Context Injection Overhead</td><td>Additional prefill from retrieved content</td></tr>
            </tbody>
          </table>
          
          <t>Corpus Constraints:</t>
          <table>
            <thead>
              <tr><th>Characteristic</th><th>Impact</th></tr>
            </thead>
            <tbody>
              <tr><td>Corpus size</td><td>Larger means longer search</td></tr>
              <tr><td>Document length</td><td>Longer means more context overhead</td></tr>
              <tr><td>Semantic diversity</td><td>More diverse reduces precision</td></tr>
            </tbody>
          </table>
          <t>Report corpus statistics: document count, average length, domain.</t>
          <t>Vector index must be fully built before measurement.</t>
        </section>
        
        <section anchor="agentic">
          <name>Agentic System Boundaries</name>
          <t>For multi-agent or tool-using systems:</t>
          
          <figure anchor="fig-agentic">
            <name>Agentic Execution Trace</name>
            <artwork type="ascii-art"><![CDATA[
                    AGENTIC EXECUTION TRACE

User Request
     |
     v
+---------+     +---------+     +---------+
| Planner |---->| Agent A |---->| Agent B |
|  (LLM)  |     |  (LLM)  |     |  (LLM)  |
+----+----+     +----+----+     +----+----+
     |               |               |
     |          +----+----+          |
     |          v         v          |
     |     +-------+ +-------+       |
     |     | Tool  | | Tool  |       |
     |     |  API  | |  DB   |       |
     |     +-------+ +-------+       |
     |          |         |          |
     |          +----+----+          |
     |               v               |
     |          +---------+          |
     +--------->|  Final  |<---------+
                | Response|
                +---------+

Trace depth: 4 (Planner -> A -> Tools -> B)
Fan-out: 2 (parallel tool calls)
Sub-requests: 3 LLM calls
            ]]></artwork>
          </figure>
          
          <t>Definitions:</t>
          <table>
            <thead>
              <tr><th>Term</th><th>Definition</th></tr>
            </thead>
            <tbody>
              <tr><td>Agent invocation</td><td>Single LLM call with specific role</td></tr>
              <tr><td>Tool call</td><td>External capability invocation</td></tr>
              <tr><td>Orchestration step</td><td>Planning/routing decision</td></tr>
              <tr><td>Trace</td><td>Complete sequence for one user request</td></tr>
            </tbody>
          </table>
          
          <t>Measurement Points:</t>
          <table>
            <thead>
              <tr><th>Metric</th><th>Start</th><th>End</th></tr>
            </thead>
            <tbody>
              <tr><td>Per-agent latency</td><td>Agent receives input</td><td>Agent produces output</td></tr>
              <tr><td>Per-tool latency</td><td>Tool call initiated</td><td>Response received</td></tr>
              <tr><td>Orchestration overhead</td><td>Previous step complete</td><td>Next step starts</td></tr>
              <tr><td>Task completion</td><td>User request received</td><td>Final response delivered</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="compound-exclusions">
          <name>Exclusions</name>
          <t>Custom user application logic and bespoke agent frameworks are out of scope. This profile covers general patterns, not specific implementations.</t>
        </section>
      </section>
    </section>

    <section anchor="workload-profiles">
      <name>Workload Profiles</name>
      <t>Workload profiles specify traffic patterns applied to infrastructure profiles. They do not define measurement boundaries.</t>
      
      <section anchor="chatbot-workload">
        <name>Chatbot Workload Profile</name>
        
        <section anchor="chatbot-characteristics">
          <name>Characteristics</name>
          <table>
            <thead>
              <tr><th>Characteristic</th><th>Description</th></tr>
            </thead>
            <tbody>
              <tr><td>Interaction</td><td>Stateful, multi-turn</td></tr>
              <tr><td>Delivery</td><td>Streaming</td></tr>
              <tr><td>Arrival</td><td>Closed-loop (user thinks between turns)</td></tr>
              <tr><td>Session length</td><td>Variable, typically 3-20 turns</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="chatbot-params">
          <name>Required Parameters</name>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Description</th><th>Example</th></tr>
            </thead>
            <tbody>
              <tr><td>Arrival model</td><td>Open or closed loop</td><td>Closed-loop</td></tr>
              <tr><td>Think-time</td><td>User delay between turns</td><td>Exponential, mean=5s</td></tr>
              <tr><td>Input length</td><td>Tokens per user message</td><td>Log-normal, median=50</td></tr>
              <tr><td>Output length</td><td>Tokens per response</td><td>Log-normal, median=150</td></tr>
              <tr><td>Context retention</td><td>History handling</td><td>Sliding window, 4K tokens</td></tr>
              <tr><td>Session length</td><td>Turns per conversation</td><td>Geometric, mean=8</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="chatbot-example">
          <name>Example</name>
          <artwork><![CDATA[
Chatbot Workload: Customer Support

Arrival: Closed-loop, 100 concurrent sessions
Think-time: Exponential(mean=8s)
Input: Log-normal(mu=4.0, sigma=0.8), range [10, 500]
Output: Log-normal(mu=5.0, sigma=1.0), range [20, 1000]
Context: Sliding window, last 4000 tokens
Session: Geometric(p=0.12), mean ~8 turns
System prompt: 200 tokens, shared
          ]]></artwork>
        </section>
      </section>
      
      <section anchor="compound-workflow">
        <name>Compound Workflow Workload Profile</name>
        
        <section anchor="workflow-characteristics">
          <name>Characteristics</name>
          <table>
            <thead>
              <tr><th>Characteristic</th><th>Description</th></tr>
            </thead>
            <tbody>
              <tr><td>Execution</td><td>Multi-step, may include parallel branches</td></tr>
              <tr><td>Tool usage</td><td>API calls, code execution, database queries</td></tr>
              <tr><td>Dependencies</td><td>Steps may depend on previous outputs</td></tr>
              <tr><td>Failure modes</td><td>Steps may fail, requiring retry or alternatives</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="workflow-params">
          <name>Required Parameters</name>
          <table>
            <thead>
              <tr><th>Parameter</th><th>Description</th><th>Example</th></tr>
            </thead>
            <tbody>
              <tr><td>Task complexity</td><td>Steps per task</td><td>Fixed=5 or distribution</td></tr>
              <tr><td>Fan-out pattern</td><td>Parallel vs sequential</td><td>Max parallel=3</td></tr>
              <tr><td>Tool latency</td><td>External dependency behavior</td><td>Real, mocked, simulated</td></tr>
              <tr><td>Failure injection</td><td>Simulated failures</td><td>5% tool failure rate</td></tr>
              <tr><td>Retry behavior</td><td>Failure handling</td><td>Max 2 retries, exponential backoff</td></tr>
            </tbody>
          </table>
        </section>
        
        <section anchor="workflow-dependencies">
          <name>External Dependency Handling</name>
          <t>Compound workflows depend on external systems. Disclose handling:</t>
          <table>
            <thead>
              <tr><th>Approach</th><th>Description</th><th>When</th></tr>
            </thead>
            <tbody>
              <tr><td>Real</td><td>Actual API calls</td><td>Production-representative</td></tr>
              <tr><td>Mocked</td><td>Fixed responses</td><td>Controlled experiments</td></tr>
              <tr><td>Simulated</td><td>Statistical model</td><td>Reproducible benchmarks</td></tr>
            </tbody>
          </table>
          <t>Report observed latency and failure rate for real dependencies. Report configured values for mocked dependencies.</t>
        </section>
      </section>
    </section>

    <section anchor="delta-measurement">
      <name>Delta Measurement Model</name>
      <t><xref target="infrastructure-profiles"/> and <xref target="workload-profiles"/> defined individual profiles. Production systems compose multiple profiles. A request may pass through Gateway, Firewall, and Engine before response generation.</t>
      
      <t>Meaningful comparison across composed systems requires attributing latency to each component. This section defines the delta measurement model.</t>
      
      <section anchor="timestamp-reference">
        <name>Timestamp Reference</name>
        <t>Consider a request flowing through a full stack:</t>
        
        <figure anchor="fig-timestamps">
          <name>Request Flow Timestamps</name>
          <artwork type="ascii-art"><![CDATA[
Client
  |
  |  t0: request sent
  v
+-------------------+
|    AI Gateway     |
|  t1: arrives      |
|  t2: exits        |
+-------------------+
  |
  v
+-------------------+
|   AI Firewall     |
|  t3: arrives      |
|  t4: decision     |
|  t5: exits        |
+-------------------+
  |
  v
+-------------------+
|   Model Engine    |
|  t6: queue entry  |
|  t6a: exec start  |
|  t7: first token  |
|  t8: last token   |
+-------------------+
  |
  v
+-------------------+
|   Output Path     |
|  t9: fw receives  |
|  t10: fw releases |
|  t11: gw releases |
+-------------------+
  |
  v
  t12: client receives first token
          ]]></artwork>
        </figure>
      </section>
      
      <section anchor="timestamp-definitions">
        <name>Timestamp Definitions</name>
        <table>
          <thead>
            <tr><th>Timestamp</th><th>Location</th><th>Event</th></tr>
          </thead>
          <tbody>
            <tr><td>t0</td><td>Client</td><td>Request transmission begins</td></tr>
            <tr><td>t1</td><td>Gateway</td><td>Request arrives</td></tr>
            <tr><td>t2</td><td>Gateway</td><td>Request exits toward firewall</td></tr>
            <tr><td>t3</td><td>Firewall</td><td>Request arrives</td></tr>
            <tr><td>t4</td><td>Firewall</td><td>Inbound decision reached</td></tr>
            <tr><td>t5</td><td>Firewall</td><td>Request exits toward engine</td></tr>
            <tr><td>t6</td><td>Engine</td><td>Request enters queue</td></tr>
            <tr><td>t6a</td><td>Engine</td><td>Prefill computation begins</td></tr>
            <tr><td>t7</td><td>Engine</td><td>First output token generated</td></tr>
            <tr><td>t8</td><td>Engine</td><td>Last output token generated</td></tr>
            <tr><td>t9</td><td>Firewall</td><td>First token arrives for outbound inspection</td></tr>
            <tr><td>t10</td><td>Firewall</td><td>First token released after inspection</td></tr>
            <tr><td>t11</td><td>Gateway</td><td>First token exits toward client</td></tr>
            <tr><td>t12</td><td>Client</td><td>Client receives first token</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="component-deltas">
        <name>Component Deltas</name>
        <table>
          <thead>
            <tr><th>Component</th><th>Formula</th><th>Measures</th></tr>
          </thead>
          <tbody>
            <tr><td>Gateway inbound</td><td>t2 - t1</td><td>Auth, validation, routing</td></tr>
            <tr><td>Firewall inbound (pass)</td><td>t5 - t3</td><td>Prompt inspection</td></tr>
            <tr><td>Firewall inbound (block)</td><td>t4 - t3</td><td>Time to block</td></tr>
            <tr><td>Engine queue</td><td>t6a - t6</td><td>Wait before execution</td></tr>
            <tr><td>Engine prefill</td><td>t7 - t6a</td><td>Prefill computation</td></tr>
            <tr><td>Engine TTFT</td><td>t7 - t6</td><td>Queue plus prefill</td></tr>
            <tr><td>Firewall outbound</td><td>t10 - t9</td><td>Output inspection</td></tr>
            <tr><td>Gateway outbound</td><td>t11 - t10</td><td>Response processing</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="e2e-metrics">
        <name>End-to-End Metrics</name>
        <table>
          <thead>
            <tr><th>Metric</th><th>Formula</th><th>Notes</th></tr>
          </thead>
          <tbody>
            <tr><td>Engine TTFT</td><td>t7 - t6</td><td>At engine boundary</td></tr>
            <tr><td>System TTFT</td><td>t12 - t0</td><td>Client-observed</td></tr>
            <tr><td>Output path overhead</td><td>t12 - t7</td><td>Delay from engine emit to client receive</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="clock-sync">
        <name>Clock Synchronization</name>
        <t>Delta metrics within a single component (t2 - t1, both from gateway clock) are reliable. Cross-component deltas (t6 - t5) require clock synchronization.</t>
        
        <t>For end-to-end metrics involving client timestamps (t0, t12), clock skew introduces error.</t>
        
        <t>Options:</t>
        <ol>
          <li>Single-machine measurement (client and server share clock)</li>
          <li>Measure and report skew bounds</li>
          <li>Report server-side metrics only when skew is too large</li>
        </ol>
        
        <t>Recommended practice: Calculate deltas within components rather than across boundaries when possible.</t>
        
        <t>See <xref target="clock-requirements"/> for synchronization requirements.</t>
      </section>
    </section>

    <section anchor="composition">
      <name>Profile Composition</name>
      
      <section anchor="composite-declaration">
        <name>Composite SUT Declaration</name>
        <t>When SUT includes multiple profiles, testers MUST:</t>
        
        <t>1. Enumerate all components in request path:</t>
        <artwork><![CDATA[
Client -> AI Gateway -> AI Firewall -> Model Engine -> AI Firewall -> Client
        ]]></artwork>
        
        <t>2. Declare measurement boundary:</t>
        <table>
          <thead>
            <tr><th>Type</th><th>Description</th></tr>
          </thead>
          <tbody>
            <tr><td>Full-stack</td><td>Client to response, all components</td></tr>
            <tr><td>Per-component</td><td>Separate measurement at each boundary</td></tr>
            <tr><td>Partial</td><td>Specific subset (e.g., Gateway + Engine)</td></tr>
          </tbody>
        </table>
        
        <t>3. Provide delta decomposition:</t>
        <artwork><![CDATA[
Component          | TTFT Contribution | Throughput Impact
-------------------|-------------------|------------------
AI Gateway         | +15ms             | -3%
AI Firewall (in)   | +45ms             | -8%
Model Engine       | 180ms (baseline)  | baseline
AI Firewall (out)  | +12ms*            | -12%
-------------------|-------------------|------------------
Total              | 252ms             | -22%

*Outbound adds to client-observed TTFT, not engine TTFT
        ]]></artwork>
      </section>
      
      <section anchor="composition-validation">
        <name>Composition Validation</name>
        <t>Measure components independently before measuring composite:</t>
        <ol>
          <li>Engine alone: TTFT_engine = 180ms</li>
          <li>Gateway + Engine: TTFT_gw = 195ms, Gateway_delta = 15ms</li>
          <li>Firewall + Engine: TTFT_fw = 225ms, Firewall_delta = 45ms</li>
          <li>Full stack: TTFT_full = 252ms</li>
          <li>Validate: TTFT_engine + deltas approximately equals TTFT_full</li>
        </ol>
        <t>If validation fails, interaction effects exist. Document them.</t>
      </section>
      
      <section anchor="interaction-effects">
        <name>Interaction Effects</name>
        <t>Components may interact beyond simple addition:</t>
        <table>
          <thead>
            <tr><th>Effect</th><th>Description</th><th>Example</th></tr>
          </thead>
          <tbody>
            <tr><td>Batching interference</td><td>Gateway batching conflicts with engine</td><td>Gateway batches 8, engine max is 4</td></tr>
            <tr><td>Cache interaction</td><td>High gateway cache hit means engine sees hard queries</td><td>Biased difficulty</td></tr>
            <tr><td>Backpressure</td><td>Slow component causes upstream queuing</td><td>Firewall slowdown grows gateway queue</td></tr>
            <tr><td>Timeout cascades</td><td>Mismatched timeouts waste resources</td><td>See below</td></tr>
          </tbody>
        </table>
        
        <t>Timeout Cascades:</t>
        <figure anchor="fig-timeout">
          <name>Timeout Cascade Example</name>
          <artwork type="ascii-art"><![CDATA[
TIMEOUT CASCADE (mismatched configurations)

Gateway timeout:  10s  -------------+
Firewall timeout: 15s  ---------------------+
Engine timeout:   30s  -------------------------------------+
                       |            |       |               |
Time: 0s              10s          15s     30s
      |                |            |       |
      +-- Request ---->|            |       |
      |                |            |       |
      |   Gateway -----X timeout    |       |
      |   (returns error to client) |       |
      |                |            |       |
      |   Firewall -----------------+       |
      |   (still waiting)           |       |
      |                             |       |
      |   Engine ---------------------------+
      |   (completes at 12s, result discarded)
      |                             |       |
      +-------------------------------------+

Result: Client gets error at 10s. Engine wastes 12s of compute.
          ]]></artwork>
        </figure>
        <t>Report timeout configurations and note mismatches.</t>
      </section>
    </section>

    <section anchor="logging">
      <name>Access Logging Requirements</name>
      
      <section anchor="minimum-fields">
        <name>Minimum Fields</name>
        <t>All profiles MUST log:</t>
        <table>
          <thead>
            <tr><th>Field</th><th>Description</th></tr>
          </thead>
          <tbody>
            <tr><td>timestamp</td><td>Request start time</td></tr>
            <tr><td>request_id</td><td>Unique identifier</td></tr>
            <tr><td>profile</td><td>Infrastructure profile under test</td></tr>
            <tr><td>workload</td><td>Workload profile applied</td></tr>
            <tr><td>latency_ms</td><td>Total request latency</td></tr>
            <tr><td>status</td><td>Success, error, timeout</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="engine-fields">
        <name>Model Engine Fields</name>
        <table>
          <thead>
            <tr><th>Field</th><th>Description</th></tr>
          </thead>
          <tbody>
            <tr><td>queue_time_ms</td><td>Time in queue</td></tr>
            <tr><td>prefill_time_ms</td><td>Prefill latency</td></tr>
            <tr><td>decode_time_ms</td><td>Generation time</td></tr>
            <tr><td>batch_size</td><td>Concurrent requests in batch</td></tr>
            <tr><td>token_count_in</td><td>Input tokens</td></tr>
            <tr><td>token_count_out</td><td>Output tokens</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="firewall-fields">
        <name>AI Firewall Fields</name>
        <table>
          <thead>
            <tr><th>Field</th><th>Description</th></tr>
          </thead>
          <tbody>
            <tr><td>direction</td><td>Inbound or outbound</td></tr>
            <tr><td>decision</td><td>Allow, block, modify</td></tr>
            <tr><td>policy_triggered</td><td>Which policy matched</td></tr>
            <tr><td>confidence</td><td>Detection confidence</td></tr>
            <tr><td>inspection_time_ms</td><td>Analysis time</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="compound-fields">
        <name>Compound System Fields</name>
        <table>
          <thead>
            <tr><th>Field</th><th>Description</th></tr>
          </thead>
          <tbody>
            <tr><td>trace_id</td><td>Identifier linking all steps</td></tr>
            <tr><td>step_count</td><td>Total orchestration steps</td></tr>
            <tr><td>tool_calls</td><td>List of tools invoked</td></tr>
            <tr><td>success_type</td><td>Hard, soft, or failure</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="gateway-fields">
        <name>AI Gateway Fields</name>
        <table>
          <thead>
            <tr><th>Field</th><th>Description</th></tr>
          </thead>
          <tbody>
            <tr><td>cache_status</td><td>Hit, miss, or bypass</td></tr>
            <tr><td>route_target</td><td>Selected backend</td></tr>
            <tr><td>token_count_in</td><td>Input tokens</td></tr>
            <tr><td>token_count_out</td><td>Output tokens</td></tr>
          </tbody>
        </table>
      </section>
      
      <section anchor="otel">
        <name>OpenTelemetry Integration</name>
        <t>OpenTelemetry integration SHOULD be supported. Reference GenAI semantic conventions when available.</t>
      </section>
    </section>

    <section anchor="measurement">
      <name>Measurement Considerations</name>
      
      <section anchor="baseline-delta">
        <name>Baseline and Delta Reporting</name>
        <t>For intermediary components (Gateway, Firewall), provide differential measurements:</t>
        <ol>
          <li>Measure downstream directly (baseline)</li>
          <li>Measure through intermediary</li>
          <li>Compute delta</li>
          <li>Report both absolute and delta</li>
        </ol>
      </section>
      
      <section anchor="warmup">
        <name>Warm-up and Steady State</name>
        <t>Declare whether results include cold start.</t>
        <table>
          <thead>
            <tr><th>Profile</th><th>Cold Start Factors</th></tr>
          </thead>
          <tbody>
            <tr><td>Model Engine</td><td>JIT compilation, KV cache allocation, batch ramp-up</td></tr>
            <tr><td>AI Gateway</td><td>Connection pool, cache population</td></tr>
            <tr><td>AI Firewall</td><td>Model loading, rule compilation</td></tr>
            <tr><td>Compound System</td><td>All above plus retrieval index loading</td></tr>
          </tbody>
        </table>
        <t>If excluding cold start, report warm-up procedure and duration.</t>
      </section>
      
      <section anchor="clock-requirements">
        <name>Clock Synchronization</name>
        <table>
          <thead>
            <tr><th>Configuration</th><th>Minimum Accuracy</th><th>Method</th></tr>
          </thead>
          <tbody>
            <tr><td>Single-machine</td><td>Inherent</td><td>N/A</td></tr>
            <tr><td>Same rack</td><td>1ms</td><td>NTP</td></tr>
            <tr><td>Distributed</td><td>100us</td><td>PTP</td></tr>
            <tr><td>Sub-millisecond analysis</td><td>10us</td><td>PTP with hardware timestamps</td></tr>
          </tbody>
        </table>
        
        <t>Reports MUST declare:</t>
        <ul>
          <li>Synchronization method</li>
          <li>Estimated maximum skew</li>
          <li>Single-point or distributed measurement</li>
        </ul>
      </section>
      
      <section anchor="streaming">
        <name>Streaming Protocol Considerations</name>
        <table>
          <thead>
            <tr><th>Profile</th><th>Recommended Protocol</th><th>Notes</th></tr>
          </thead>
          <tbody>
            <tr><td>Model Engine</td><td>gRPC streaming</td><td>Lower overhead</td></tr>
            <tr><td>AI Gateway</td><td>SSE over HTTP</td><td>Broad compatibility</td></tr>
            <tr><td>AI Firewall</td><td>Match upstream/downstream</td><td>Minimize translation</td></tr>
            <tr><td>Compound System</td><td>SSE or WebSocket</td><td>Client dependent</td></tr>
          </tbody>
        </table>
        <t>Report chunk size distribution when measuring ITL.</t>
      </section>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>
      
      <section anchor="bidirectional-gaps">
        <name>Bidirectional Enforcement Gaps</name>
        <t>AI Firewalls enforcing only one direction leave systems exposed.</t>
        
        <t>Inbound-only gaps:</t>
        <ul>
          <li>Cannot prevent PII leakage</li>
          <li>Cannot catch policy violations from model</li>
          <li>Cannot stop tool misuse</li>
        </ul>
        
        <t>Outbound-only gaps:</t>
        <ul>
          <li>Cannot prevent prompt injection</li>
          <li>Cannot stop jailbreak attempts</li>
          <li>Malicious content reaches model</li>
        </ul>
        
        <t>Declare which directions are enforced. "AI Firewall protection" without direction is incomplete.</t>
      </section>
      
      <section anchor="adversarial-handling">
        <name>Adversarial Workload Handling</name>
        <t>Security requirements for adversarial benchmarks:</t>
        <ul>
          <li>Samples MUST NOT contain working exploits</li>
          <li>Use sanitized patterns or synthetic constructs</li>
          <li>Reference published taxonomies (OWASP LLM Top 10, MITRE ATLAS)</li>
          <li>Do not publish novel attacks discovered during testing</li>
        </ul>
      </section>
      
      <section anchor="side-channels">
        <name>Side-Channel Considerations</name>
        <t>Performance characteristics may leak information:</t>
        <table>
          <thead>
            <tr><th>Channel</th><th>Risk</th><th>Mitigation</th></tr>
          </thead>
          <tbody>
            <tr><td>Timing</td><td>Decision time reveals classification</td><td>Add noise</td></tr>
            <tr><td>Cache</td><td>Hit patterns reveal similarity</td><td>Per-tenant isolation</td></tr>
            <tr><td>Routing</td><td>Balancing reveals backend state</td><td>Randomize</td></tr>
          </tbody>
        </table>
        <t>Multi-tenant benchmarks SHOULD measure side-channel exposure.</t>
      </section>
    </section>
  </middle>

  <back>
    <references>
      <name>References</name>
      
      <references>
        <name>Normative References</name>
        
        <reference anchor="I-D.gaikwad-llm-benchmarking-terminology">
          <front>
            <title>Benchmarking Terminology for Large Language Model Serving</title>
            <author fullname="Madhava Gaikwad" initials="M." surname="Gaikwad"/>
            <date year="2026"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-gaikwad-llm-benchmarking-terminology"/>
        </reference>
        
        <reference anchor="I-D.gaikwad-llm-benchmarking-methodology">
          <front>
            <title>Benchmarking Methodology for Large Language Model Serving</title>
            <author fullname="Madhava Gaikwad" initials="M." surname="Gaikwad"/>
            <date year="2026"/>
          </front>
          <seriesInfo name="Internet-Draft" value="draft-gaikwad-llm-benchmarking-methodology"/>
        </reference>
        
        <reference anchor="RFC2119" target="https://www.rfc-editor.org/info/rfc2119">
          <front>
            <title>Key words for use in RFCs to Indicate Requirement Levels</title>
            <author fullname="S. Bradner" initials="S." surname="Bradner"/>
            <date month="March" year="1997"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="2119"/>
          <seriesInfo name="DOI" value="10.17487/RFC2119"/>
        </reference>
        
        <reference anchor="RFC8174" target="https://www.rfc-editor.org/info/rfc8174">
          <front>
            <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
            <author fullname="B. Leiba" initials="B." surname="Leiba"/>
            <date month="May" year="2017"/>
          </front>
          <seriesInfo name="BCP" value="14"/>
          <seriesInfo name="RFC" value="8174"/>
          <seriesInfo name="DOI" value="10.17487/RFC8174"/>
        </reference>
      </references>
      
      <references>
        <name>Informative References</name>
        
        <reference anchor="RFC2647" target="https://www.rfc-editor.org/info/rfc2647">
          <front>
            <title>Benchmarking Terminology for Firewall Performance</title>
            <author fullname="D. Newman" initials="D." surname="Newman"/>
            <date month="August" year="1999"/>
          </front>
          <seriesInfo name="RFC" value="2647"/>
        </reference>
        
        <reference anchor="RFC3511" target="https://www.rfc-editor.org/info/rfc3511">
          <front>
            <title>Benchmarking Methodology for Firewall Performance</title>
            <author fullname="B. Hickman" initials="B." surname="Hickman"/>
            <author fullname="D. Newman" initials="D." surname="Newman"/>
            <author fullname="S. Tadjudin" initials="S." surname="Tadjudin"/>
            <author fullname="T. Martin" initials="T." surname="Martin"/>
            <date month="April" year="2003"/>
          </front>
          <seriesInfo name="RFC" value="3511"/>
        </reference>
        
        <reference anchor="OWASP-LLM" target="https://owasp.org/www-project-top-10-for-large-language-model-applications/">
          <front>
            <title>OWASP Top 10 for Large Language Model Applications</title>
            <author>
              <organization>OWASP Foundation</organization>
            </author>
            <date year="2023"/>
          </front>
        </reference>
        
        <reference anchor="BIPIA" target="https://arxiv.org/abs/2312.14197">
          <front>
            <title>Benchmarking and Defending Against Indirect Prompt Injection Attacks on Large Language Models</title>
            <author fullname="Jingwei Yi" initials="J." surname="Yi"/>
            <author fullname="Yueqi Xie" initials="Y." surname="Xie"/>
            <author fullname="Bin Zhu" initials="B." surname="Zhu"/>
            <author fullname="Keegan Hines" initials="K." surname="Hines"/>
            <author fullname="Emre Kiciman" initials="E." surname="Kiciman"/>
            <author fullname="Guangzhong Sun" initials="G." surname="Sun"/>
            <author fullname="Xing Xie" initials="X." surname="Xie"/>
            <date year="2023"/>
          </front>
        </reference>
        
        <reference anchor="DISTSERVE" target="https://www.usenix.org/conference/osdi24/presentation/zhong-yinmin">
          <front>
            <title>DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving</title>
            <author fullname="Yinmin Zhong" initials="Y." surname="Zhong"/>
            <author fullname="Shengyu Liu" initials="S." surname="Liu"/>
            <author fullname="Junda Chen" initials="J." surname="Chen"/>
            <author fullname="Jianbo Hu" initials="J." surname="Hu"/>
            <author fullname="Yibo Zhu" initials="Y." surname="Zhu"/>
            <author fullname="Xuanzhe Liu" initials="X." surname="Liu"/>
            <author fullname="Xin Jin" initials="X." surname="Jin"/>
            <author fullname="Hao Zhang" initials="H." surname="Zhang"/>
            <date year="2024"/>
          </front>
          <seriesInfo name="OSDI" value="2024"/>
        </reference>
        
        <reference anchor="MOONCAKE" target="https://arxiv.org/abs/2407.00079">
          <front>
            <title>Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving</title>
            <author fullname="Ruoyu Qin" initials="R." surname="Qin"/>
            <author fullname="Zheming Li" initials="Z." surname="Li"/>
            <author fullname="Weiran He" initials="W." surname="He"/>
            <author fullname="Mingxing Zhang" initials="M." surname="Zhang"/>
            <author fullname="Yongwei Wu" initials="Y." surname="Wu"/>
            <author fullname="Weimin Zheng" initials="W." surname="Zheng"/>
            <author fullname="Lidong Zhou" initials="L." surname="Zhou"/>
            <date year="2024"/>
          </front>
        </reference>
      </references>
    </references>

    <section anchor="report-structure">
      <name>Example Benchmark Report Structure</name>
      <artwork><![CDATA[
1. Executive Summary
   - SUT and profile(s) used
   - Key results

2. System Configuration
   - Hardware
   - Software versions
   - Profile-specific config (per Section 4)

3. Workload Specification
   - Workload profile
   - Parameters (per Section 5)
   - Dataset sources

4. Methodology
   - Measurement boundary
   - Clock synchronization
   - Warm-up procedure
   - Duration and request counts

5. Results
   - Primary metrics with percentiles
   - Secondary metrics
   - Delta decomposition (if composite)

6. Analysis
   - Observations
   - Interaction effects
   - Limitations

7. Reproduction
   - Config files
   - Scripts
   - Random seeds
      ]]></artwork>
    </section>

  </back>
</rfc>
