Skip to content

Research notes / RAID layout

Parity declustering: less load per disk, not fewer reads

13 October 2026 / Source review and executable accounting

A repair can read exactly the same number of bytes while making each busy disk do less work. The missing distinction is between how wide each parity stripe is and how widely those stripes are placed.

Stripe width and pool width are different

Holland and Gibson separate stripe width G, including parity, from pool size C. Balanced pair membership spreads reconstruction work. Their single-parity model gives a survivor-read fraction of (G - 1) / (C - 1) and parity capacity fraction 1 / G. [1, sections 2 and 4]

This does not mean that widening a stripe and spreading an unchanged stripe are equivalent optimizations. The comparison below keeps both pool size and lost bytes constant, then changes one decision at a time.

Same missing bytes, two different load profiles

Hesela enumerates all 70 four-disk subsets of eight disks. Every disk appears in 35 stripes; every pair appears together in 15. Each stripe has one parity fragment and equal 64 MiB fragments. Disk 0 fails. No other read errors occur.

The fixed-group control repeats stripes on disks 0-3 and 4-7 thirty-five times each. Both layouts store 35 fragments per disk, reserve 25% of raw space for parity and lose 2,240 MiB. They both need 105 helper-fragment reads, or 6,720 MiB, plus 2,240 MiB of reconstructed output.

Computed examples, not measured I/O. All cases: eight disks and 35 lost 64 MiB fragments.
LayoutParity / rawTotal helper readsPeak reads on one survivorSurvivors used
Two fixed groups, width 425%105353
Balanced groups, width 425%105157
One wide group, width 812.5%245357
Per-survivor work: fixed versus balanced width-four groups

Counts of 64 MiB helper fragments. Same zero baseline and scale, 0-35.

Disk 1
Fixed35
Balanced15
Disk 2
Fixed35
Balanced15
Disk 3
Fixed35
Balanced15
Disk 4
Fixed0
Balanced15
Disk 5
Fixed0
Balanced15
Disk 6
Fixed0
Balanced15
Disk 7
Fixed0
Balanced15

The busiest survivor falls from 35 reads to 15, a 57.14% reduction in its read count, while total reads remain unchanged. Disks 4-7 go from idle to helping. This is work redistribution, not a 57.14% measured speedup.

The width-eight control changes a second variable: each missing fragment needs seven helpers instead of three. It reads 245 fragments, or 15,680 MiB, and reserves 12.5% for parity. It holds more payload in the same raw space. Attributing this whole difference to placement alone would confound stripe width with layout.

Download all 21 survivor rows, JSON provenance and runnable code. This page calculates its values from the same module; zero-read survivors are retained.

What the experiments establish

The 1992 study used raidSim, synthetic 4 KB requests and a modeled IBM 0661 disk. Its 21-disk simulations used five independently seeded runs per plotted point. It did not measure modern SSDs; the model omitted CPU XOR time. It also found that fewer operations need not shorten recovery when positioning costs intervene. [1, sections 5-8]

The Panasas paper describes actual reconstruction tests with 10-120 storage nodes and 1-12 DirectorBlades. Files were 100 MB or 1 GB. Its reported rebuild rate was lost-node used capacity divided by reconstruction wall time, not aggregate helper-read bandwidth. The implementation distributed output writes and computation as well as reads. These factors matter when interpreting its scaling result. [2, section 4.2 and Appendix A]

Our enumeration reproduces neither experiment. It establishes exact membership counts only. No confidence interval applies to these exhaustive, deterministic counts; uncertainty about their applicability to a real array remains.

dRAID adds allocation and verification tradeoffs

OpenZFS dRAID distributes spare space and rebuild I/O using permutation maps, not this toy's complete-subset listing. Its fixed stripe width can add padding: the documentation's D=8, 4 KiB-sector example has a 32 KiB minimum allocation, potentially reducing effective compression for small blocks. [3]

A sequential resilver repairs allocated regions without checking block checksums during that pass; OpenZFS starts a scrub afterward. A healing resilver can verify block checksums during repair. Finishing the sequential phase and finishing the subsequent verification are distinct milestones. [3, Rebuilding to a Distributed Spare]

A wider repair pool is not a free durability gain

In our single-parity example, losing disks 0 and 4 leaves the fixed groups with one erasure each. The balanced layout instead has 15 stripes containing both disks, beyond their one-erasure budget. This is an explicit erasure-pattern counterexample, not a field failure probability. It says nothing by itself about the risk after accounting for repair speed and correlated failures.

Parity positions, byte offsets, spare-write destinations, caching, network links, queueing, seeks, metadata and foreground traffic are not modeled. The module deliberately bounds pool size to 16: enumerating all subsets is a teaching technique, not a scalable production placement algorithm.

For an operational comparison, report stripe width, placement scope, parity overhead, lost bytes, aggregate reads, busiest-survivor reads, output-write destinations, foreground latency and checksum-verification status separately. A spare-write bottleneck can remain even when read load is balanced.

Continue with repair locality and parity-inclusive denominators and what scrubbing can establish. Definitions: parity declustering and distributed spare.

Sources and method

  1. Mark Holland and Garth A. Gibson. Parity Declustering for Continuous Operation in Redundant Disk Arrays. ASPLOS 1992, pp. 23-35; sections 2, 4-8.
  2. Brent Welch, Marc Unangst, Zainul Abbasi, Garth Gibson, Brian Mueller, Jason Small, Jim Zelenka and Bin Zhou. Scalable Performance of the Panasas Parallel File System. FAST 2008; section 4.2 and Appendix A, experiment 3.
  3. OpenZFS: dRAID how-to, Introduction and Rebuilding to a Distributed Spare (living documentation, functionality introduced in 2.1.0).

Sources accessed 13 October 2026. Literature synthesis plus original deterministic accounting; no storage benchmark or fault injection was performed.