:{#metadata
banner="zfs_hierarchy.png"
}
# ZFS Calculators
---
A collection of calculators from around the web, for the [ZFS][] filesystem.
This was mainly done to preserve them in one place, and to experiment with
using [PyScript][] (allows python to be used for browser scripting instead of
javascript).
If you don't know much about ZFS, or need to brush up on your knowledge,
["OpenZFS: the final word in file systems"][] by Jason Rose is a fantastic
introduction.
[ZFS]: https://en.wikipedia.org/wiki/ZFS
[PyScript]: https://pyscript.net
["OpenZFS: the final word in file systems"]: https://jro.io/truenas/openzfs
\
## RAIDZ Expansion
---
The latest TrueNAS ([Electric-Eel / 24.10][]) now supports RAIDZ expansion,
which allows you to append disks to an existing vdev. This allows you to extend
you're vdevs over time, rather than having to erase the vdev, create a new one,
and restore from backup. It has one small caveat however, which is that the
existing data still uses the data-to-parity ratio and block width of the old
vdev size. This effectively means that you don't get the full capacity of your
drives until that existing data is rewritten. If you're interested in recovering
that capacity, check out [ZFS In-Place Rebalancing][] by Markus Ressel.
This calculator, based on the TrueNAS [RAIDZ extension calculator][], allows
you to determine how much space is lost compared to creating a new vdev from
scratch.
[Electric-Eel / 24.10]: https://www.truenas.com/docs/scale/24.10/gettingstarted/scalereleasenotes
[ZFS In-Place Rebalancing]: https://github.com/markusressel/zfs-inplace-rebalancing
[RAIDZ extension calculator]: https://www.truenas.com/docs/references/extensioncalculator
---
:::: side-by-side
:::
```=html
```
:::
:::
```=html
Extend VDEV to final width all at onceExtend VDEV one drive at a time
```
:::
::::
```=pyscript
from pyscript import document
def calculate(event):
# Convert inputs
drive_size = int(document.querySelector("#drive_size_input").value)
raidz_level = int(document.querySelector("#raidz_level_input").value)
expansion = float(document.querySelector("#expansion_input").value)
initial_drives = int(document.querySelector("#initial_input").value)
final_drives = int(document.querySelector("#final_input").value)
# Results for installing all drives at once
expansionPercent = expansion / 100
percentage_decrease = (final_drives - initial_drives) / final_drives
drives_worth_recovered = expansionPercent * raidz_level * percentage_decrease
capacity_recovered = drive_size * drives_worth_recovered
total_capacity_recovered = drives_worth_recovered / final_drives
document.querySelector("#capacity_recovered").innerText = f"{capacity_recovered:.2f} TB"
document.querySelector("#drives_worth_recovered").innerText = f"{drives_worth_recovered:.2f} Drives"
document.querySelector("#total_capacity_recovered").innerText = f"{total_capacity_recovered:.2%}"
# Results for installing drives one at a time
# Calculate the sum of a finite harmonic series
harmonic_sum = sum(1 / i for i in range(initial_drives + 1, final_drives + 1))
drives_worth_recovered_compound = expansionPercent * raidz_level * harmonic_sum
capacity_recovered_compound = drive_size * drives_worth_recovered_compound
total_capacity_recovered_compound = drives_worth_recovered_compound / final_drives
document.querySelector("#capacity_recovered_compound").innerText = f"{capacity_recovered_compound:.2f} TB"
document.querySelector("#drives_worth_recovered_compound").innerText = f"{drives_worth_recovered_compound:.2f} Drives"
document.querySelector("#total_capacity_recovered_compound").innerText = f"{total_capacity_recovered_compound:.2%}"
```