> ## Content Index
> Fetch the complete content index at: https://globaltrendanalysis.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Bottleneck Analysis
- URL: https://globaltrendanalysis.com/bottleneck-analysis/
- Published: 2026-09-11T02:07:43.000Z
- Updated: 2026-09-11T02:07:42.000Z
- Author: Aaron Lucas
- Tags: Storage / SSD

# SSD Bottleneck Analysis

*A working page for modeling SSD performance as a series of capacity-constrained stages. Fill in device-specific numbers as they're gathered.*

## Method

Model the SSD data path as a chain of stages, each with its own maximum throughput (a "capacity," in the same sense as an arc in a transportation/network-flow problem). Data has to pass through every stage on the way from host to media, so the achievable end-to-end performance is bounded by the slowest stage:

```
SSD_Throughput(workload) = min( Stage_1, Stage_2, ..., Stage_N )

```

This is the same logic as a max-flow / min-cut problem: within a stage, parallel resources (lanes, channels, dies, planes) add capacity, but across stages the pipeline can only move data as fast as its narrowest link. The "bottleneck stage" is the equivalent of the minimum-capacity cut.

Two practical wrinkles versus a textbook transportation problem:

- **Units must match before taking the min.** Some stages are naturally bandwidth-bound (GB/s) and others are naturally operation-bound (IOPS). Convert using the workload's block size: `BW = IOPS x block_size` and `IOPS = BW / block_size`. Which stages dominate depends on whether the workload is large-block/sequential (bandwidth-bound stages tend to win) or small-block/random (IOPS-bound stages tend to win).
- **The bottleneck can be time-varying.** SLC write cache means the true minimum is different in "burst" mode (writing into cache) versus "sustained" mode (cache exhausted, writing/folding into native TLC/QLC). Compute both regimes separately.

---

## Candidate Bottleneck Stages

### 1\. Host Interface (PCIe link)

```
BW_host = N_lanes x LineRate_GT/s x EncodingEfficiency / 8      [GB/s]

```

- `N_lanes`: e.g., x4
- `LineRate_GT/s`: Gen3 = 8, Gen4 = 16, Gen5 = 32
- `EncodingEfficiency`: 128b/130b ≈ 0.9846 (Gen3+); 8b/10b = 0.8 (Gen1/2)
- Subtract \~5-10% for NVMe/TLP framing overhead to get a realistic *usable* number.
- Example: Gen4 x4 → 4 x 16 x 0.9846 / 8 ≈ 7.88 GB/s raw.

### 2\. Controller Compute / FTL / Command Processing

```
IOPS_controller = N_cores x Clock_freq / CyclesPerCommand

```

or, if only a vendor spec is available, treat the published max IOPS number as this stage's capacity directly. Covers L2P (logical-to-physical) address translation, queue/doorbell handling, and command parsing. This is usually the limiter for small-block random IOPS on cheap/DRAM-less controllers.

### 3\. DRAM Bandwidth (mapping table / cache)

```
BW_DRAM = DataRate_MTs x BusWidth_bits / 8 x N_channels          [GB/s]
IOPS_DRAM = BW_DRAM / Bytes_DRAM_access_per_IO

```

- Each random IO needs L2P table read/update (a few bytes per 4KB mapped, more if page-level mapping) plus any data caching.
- DRAM-less (HMB-based) designs borrow host memory instead — same math, but `BW_DRAM` is then constrained by the PCIe link too.

### 4\. ECC / LDPC Encode-Decode Engine

```
BW_ECC = CodewordSize x DecodeRate_codewords_per_sec x N_engines   [GB/s]

```

- Must exceed the raw NAND throughput at the required BER (bit error rate).
- Degrades over drive life: more read-retry / decode iterations near end-of-life reduces effective `DecodeRate`.

### 5\. NAND Flash Interface (channel bus / Toggle / ONFI)

```
BW_channel_total = InterfaceClock_MTs x BusWidth_bytes x N_channels   [GB/s]

```

- Example: Toggle NAND at 800 MT/s, 1-byte bus, 8 channels → 0.8 x 1 x 8 = 6.4 GB/s aggregate raw.
- This is a hard ceiling independent of how fast the NAND array itself can program/read.

### 6\. NAND Media / Array (program, read, erase)

```
BW_media = (PageSize x Planes x Dies_per_channel x N_channels) / t_op   [GB/s]
IOPS_media = (Planes x Dies_per_channel x N_channels) / t_op

```

- `t_op` \= `t_PROG` (write), `t_R` (read), or amortized `t_BERS / pages_per_block` (erase).
- This is the fundamental physical-array limit, parallelized across planes/dies/channels.
- TLC/QLC `t_PROG` is much slower than SLC `t_PROG` — see SLC cache section below.

### 7\. SLC (pseudo-SLC) Write Cache — Burst vs. Sustained

```
Burst_BW        = BW_media computed in SLC mode (1 bit/cell; fastest t_PROG)
Sustained_BW     = BW_media computed in native mode (TLC/QLC) minus folding overhead
Time_to_exhaust  = SLC_Cache_Size / (Host_Write_Rate)                 [if no concurrent folding]

```

- Once the SLC cache fills, the drive must fold (relocate) data from SLC to native TLC/QLC in the background, competing with host writes for NAND interface + media bandwidth.
- A simple sustained-state approximation:  
`Sustained_BW ≈ BW_media(native) / (1 + FoldingOverheadFraction)`

### 8\. Sustained Random Write / Garbage-Collection-Bound Throughput

```
BW_host_sustainable = BW_media / WAF

```

- `WAF` (Write Amplification Factor) = total NAND bytes written / host bytes written. GC relocates valid data, consuming NAND media + channel bandwidth that would otherwise serve host writes.
- This is the stage most sensitive to workload (random vs. sequential, fill level, over-provisioning) — WAF can range from \~1.05x (sequential/FDP-managed) to 3-5x (worst-case random on a nearly-full drive).

### 9\. Queue Depth / Concurrency Ceiling (Little's Law)

```
IOPS_QD = QD / Latency_per_op

```

- Even if every downstream stage has spare capacity, the host can't exceed this if it doesn't issue enough outstanding commands to keep all channels/dies busy.
- Useful as a sanity check: `Required_QD_to_saturate = IOPS_media_stage x Latency_per_op`.

### 10\. Power / Thermal Throttling

```
Sustained_BW_thermal = Peak_BW x Duty_Cycle_allowed(T, PowerBudget)

```

- No clean closed form — usually an empirical throttling curve from vendor data (clock/parallelism reduced above a temperature or power threshold).
- Matters most for sustained sequential workloads and small form factors (M.2 without heatsink).

---

## Aggregation

Convert every stage to the same unit for the workload of interest (GB/s for large-block/sequential, IOPS for small-block/random — or convert one to the other via block size), then:

```
SSD_Throughput(workload) = min(
    BW_host,
    IOPS_controller (x block_size if comparing to BW),
    BW_DRAM / IOPS_DRAM,
    BW_ECC,
    BW_channel_total,
    BW_media (or BW_media / WAF for sustained random writes),
    Burst_BW or Sustained_BW (SLC cache, depending on time regime),
    IOPS_QD,
    Sustained_BW_thermal
)

```

Compute this separately for each regime of interest — e.g., burst sequential write, sustained sequential write, random read QD1, random read QD32, sustained random write — since the binding stage typically differs across them.

---

## Worked Example (template — fill in with real spec values)

| Stage                       | Formula | Inputs needed              | Computed (GB/s) | Computed (IOPS @ 4K) | Notes |
| --------------------------- | ------- | -------------------------- | --------------- | -------------------- | ----- |
| Host interface (PCIe)       | §1      | lanes, gen                 |                 |                      |       |
| Controller compute          | §2      | vendor spec or cores/clock |                 |                      |       |
| DRAM bandwidth              | §3      | DRAM type, width, channels |                 |                      |       |
| ECC engine                  | §4      | codeword size, decode rate |                 |                      |       |
| NAND interface              | §5      | interface speed, channels  |                 |                      |       |
| NAND media (native)         | §6      | t\_PROG/t\_R, planes, dies |                 |                      |       |
| SLC cache (burst)           | §7      | SLC t\_PROG, cache size    |                 |                      |       |
| Sustained write (WAF-bound) | §8      | WAF estimate               |                 |                      |       |
| Queue depth ceiling         | §9      | QD, latency                |                 |                      |       |
| Thermal                     | §10     | throttle curve             |                 |                      |       |
| **Bottleneck (min)**        |         |                            |                 |                      |       |

---

## TODO — Spec Values to Gather Per Drive

- \[ \] PCIe generation and lane count
- \[ \] Controller model and rated max IOPS (vendor spec)
- \[ \] DRAM type/size/width (or DRAM-less / HMB)
- \[ \] NAND type (SLC/TLC/QLC), channel count, interface speed (Toggle/ONFI, MT/s)
- \[ \] t\_PROG, t\_R, t\_BERS (from NAND datasheet or measured)
- \[ \] Planes per die, dies per channel
- \[ \] SLC (pseudo-SLC) cache size and mode (static/dynamic)
- \[ \] Expected/measured WAF for target workload
- \[ \] Thermal throttle temperature and duty-cycle behavior

## Open Questions / Next Steps

- Decide which workload profiles to model first (seq read/write, rand read/write at a few QDs).
- Pick a reference drive (or several) to populate the worked-example table with real numbers.
- Cross-check computed bottleneck against published/measured benchmark numbers to validate the model.