blob: 009e094070a05e48ee0b7dc665f2e9279af8ac2d [file] [log] [blame] [view]
# Fuchsia Filesystem Benchmarks
## Benchmarks
There are 12 benchmarks that get run for every filesystem. The currently supported filesystems are
Fxfs, F2fs, Memfs, and Minfs.
### IO Benchmarks
The IO benchmarks are all of the combinations of read/write, sequential/random, and warm/cold. Every
read/write call uses an 8KiB buffer and each operation is performed 1024 times spread across an 8MiB
file. The benchmarks measure how long each read/write operation takes.
* **Read**: makes `pread` calls to the file.
* **Cold**: the file is written, the filesystem is remounted, then we measure the time to read the
file.
* **Warm**: same as cold but without remounting.
* **Write**: makes `pwrite` call to the file.
* **Cold**: we create a new file, then measure the time to write to it.
* **Warm**: we create a new file, write to it (to populate it), then measure the time to write to
it a second time.
* **Sequential**: the reads/writes are performed sequentially from the start of the file to the end
of the file.
* **Sparse**: the reads/writes are performed linearly but sparsely, with large gaps where no data is
read/written between the accessed regions.
* **Random**: the reads/writes are performed randomly across the entire file. Every part of the file
is accessed exactly once.
* **Fsync**: the fsync is performed for every write.
### WalkDirectoryTree Benchmarks
The `WalkDirectoryTree` benchmarks measure how long it takes to walk a directory tree with POSIX
`readdir` calls. The directory tree consists of 62 directories and 189 files and is traversed 20
times by the benchmarks. The "cold" variant of the benchmarks remounts the filesystem between each
traversal and the "warm" variant does not.
### OpenFile Benchmarks
The `OpenFile` benchmark measures how long it takes for a filesystem to open a file.
The `OpenDeeplyNestedFile` benchmark expands on the `OpenFile` benchmark by placing the file several
directories deep and then opening it from the root of the filesystem. When compared to the
`OpenFile` benchmark, the `OpenDeeplyNestedFile` captures how long it takes the filesystem to
internally traverse directories.
### StatPath Benchmark
The `StatPath` benchmark measure how long it takes to call `stat` on a path to a file.
### GitStatus Benchmark
The `GitStatus` benchmark mimics the filesystem usage pattern of running `git status`. The benchmark
contains 2 phases:
* Phase 1: Calling `fstatat` on all of the files in the index to see if any of them have changed.
All of the `fstatat` calls happen relative to the top level directory.
* Phase 2: Walking the directory tree in a recursive DFS order to see if any new files were added.
### Blob Benchmarks
The `PageInBlob` benchmarks measure page fault times for mmap'ed blobs.
* `PageInBlobSequentialUncompressed` creates an incompressible blob and pages it in by sequentially
accessing each page.
* `PageInBlobSequentialCompressed` creates a compressible blob and pages it in by sequentially
accessing each page.
* `PageInBlobRandomCompressed` creates a compressible blob and randomly accesses 60% of the pages in
a way similar to executing an executable. Only 60% of pages are accessed to try to mimic an
executable starting.
The blob writing benchmarks measure how long it takes to write blobs. This is important for both
fast updates in production and development workflows.
* `WriteBlob` writes a single realistically compressible blob to a blob filesystem.
* `WriteRealisticBlobs` creates several realistically compressible blobs with varying sizes and
concurrently writes 2 blobs to a blob filesystem. This ideally mimics how pkg-cache writes blobs.
The benchmark measure how long it takes to write all of the blobs.
The `OpenAndGetVmo` benchmarks measure how long it takes to open a package and
get the VMO for a blob within it. Notably, `OpenAndGetVmo` goes through the
package directory as opposed to directly opening the blob through Blobfs/Fxblob,
and thus allows us to more accurately measure open times via SWD.
* `OpenAndGetVmoMetaFile` creates and opens a metafile (prefix "meta/" in the resource path).
* `OpenAndGetVmoContentBlob` creates and opens a content blob (non-"meta" prefix in the
resource path i.e. "data/").
## "Cold" Benchmarks
At the beginning of most benchmarks is a setup phase that creates files within the filesystem.
Simply closing all handles to those files doesn't guarantee that the filesystem will immediately
clear all caches related to those files. If the caches aren't cleared then the benchmark may only
ever hit cached (warm) data. "Cold" (uncached) read benchmarks remount the Fuchsia filesystem before
doing their read operations. Remounting the filesystem guarantees that all data related the file
that isn't normally cached gets dropped.
### Memfs and Cold Writes
When cold writing to memfs, the kernel needs to allocate pages for the VMO backing the file as the
pages are used. This causes cold writes to be slower than warm writes which have the pages already
allocated.
### Verity Benchmarks
The verity benchmarks are implemented as a Starnix integration test. The test launches a Linux
program that creates and writes a new file and then enables verity on it. The test then clears
the filesystem cache and then launches a second Linux program that performs a verified read on
the verity-enabled file. The benchmark has two metrics: 1) The time to enable verity 2) Time to
perform a verified read.
## Framework
The Fuchsia Filesystem Benchmarks use a custom framework for timing filesystem operations.
Filesystems hold state external to the `read` or `write` operations being benchmarked which can lead
to drastically different timings between consecutive operations. For other performance tests, we
want to treat the initial one or more iterations as warm-up iterations and drop their timings. (For
example, for some IPC performance tests, the initial iteration doesn't complete until a subprocess
has finished starting up, making it much slower than the later iterations.) These storage tests
differ in that we don't want to drop the initial iterations' timings.
> Ex. On the first `read` operation to a file in Minfs, Minfs reads the entire file into memory and
> each subsequent `read` is served from memory. The warm-up phase of [fuchsia-criterion] would hide
> the extremely slow `read` call.
## Running the Benchmarks
1. Include `//src/storage/benchmarks` in `fx set`.
2. Run `fx test fuchsia-pkg://fuchsia.com/storage-benchmarks#meta/storage-benchmarks.cm`
3. If you are running on an emulator, you will need to run the emulator in UEFI mode:
```sh
ffx emu start --net tap -H --uefi \
--vbmeta-key \
third_party/android/platform/external/avb/test/data/testkey_atx_psk.pem \
--vbmeta-key-metadata \
third_party/android/platform/external/avb/test/data/atx_metadata.bin
```
The set of benchmarks and filesystems can filtered with the `--filter` flag.
[fuchsia-criterion]: https://fuchsia.googlesource.com/fuchsia/+/HEAD/src/developer/fuchsia-criterion