Posted on
Artificial Intelligence

Artificial Intelligence File System Optimisation

Author
  • User
    linuxbash
    Posts by this author
    Posts by this author

Artificial Intelligence File System Optimisation on Linux (with Bash-friendly examples)

Your disks are fast, your CPUs are idle, and yet your apps pause at the worst moments. The bottleneck is often the file system and I/O path—but it doesn’t have to be guesswork. With a tiny slice of telemetry and a bit of machine learning, you can tune Linux storage like a pro: find hot spots, forecast load spikes, and apply targeted, safe optimisations that actually move the needle.

This article shows you a practical, Bash-first way to use AI/ML to guide file system optimisation, complete with install commands for apt, dnf, and zypper. You’ll collect signals, learn from them, and apply changes you can roll back quickly.


Why AI for file system optimisation?

  • Workloads are dynamic: Manual tuning based on one benchmark won’t match Monday morning email storms or month-end batch jobs.

  • Signals are noisy: Device health, queue depths, atime updates, readahead, schedulers, and mount options interact in non-obvious ways.

  • AI excels at patterns: Unsupervised learning can flag “hot hours,” unusual latency bursts, and files/directories that dominate I/O so you invest effort where it matters.

The value: measurable latency reduction, fewer stalls during critical windows, smarter data placement, and safer, incremental tweaks grounded in your own telemetry.


Prerequisites: tools you’ll use

We’ll need:

  • sysstat (iostat, pidstat)

  • iotop (per-process I/O)

  • fio (baseline testing)

  • bpftrace (optional deep tracing)

  • smartmontools, nvme-cli, hdparm (device health/params)

  • e2fsprogs, xfsprogs (filesystem utilities)

  • Python 3 with pip and venv (for light ML)

Install everything in one go for your distro:

Apt (Debian/Ubuntu):

sudo apt update && sudo apt install -y \
  sysstat iotop fio bpftrace smartmontools nvme-cli hdparm \
  e2fsprogs xfsprogs python3 python3-pip python3-venv
sudo systemctl enable --now sysstat

DNF (Fedora/RHEL/CentOS Stream):

sudo dnf install -y \
  sysstat iotop fio bpftrace smartmontools nvme-cli hdparm \
  e2fsprogs xfsprogs python3 python3-pip
sudo systemctl enable --now sysstat

Zypper (openSUSE/SLE):

sudo zypper refresh && sudo zypper install -y \
  sysstat iotop fio bpftrace smartmontools nvme-cli hdparm \
  e2fsprogs xfsprogs python3 python3-pip python3-virtualenv
sudo systemctl enable --now sysstat

Optional sanity checks:

sudo smartctl -H /dev/sda
sudo nvme smart-log /dev/nvme0

The AI-driven workflow (5 actionable steps)

1) Gather I/O telemetry you can trust

Create a lightweight collector that runs for a few minutes during a normal workload (repeat at different times of day).

sudo mkdir -p /var/log/ai-fs && sudo chown "$USER" /var/log/ai-fs

# 10-second samples, 6 times (1 minute)
iostat -dxm 10 6 > /var/log/ai-fs/iostat.txt

# Per-process disk usage snapshots every 5s for 1 min
sudo iotop -b -qqq -o -d 5 -n 12 > /var/log/ai-fs/iotop.txt

# Track disk I/O by process (pidstat), 10s interval, 6 times
pidstat -d 10 6 > /var/log/ai-fs/pidstat.txt

# Optional: short bpftrace to observe read latency histogram (root)
sudo bpftrace -e 'kprobe:blk_account_io_start { @q[probe] = hist(arg2); } interval:s:10 { print(@q); clear(@q); }' \
  > /var/log/ai-fs/bpf-lat.txt 2>/dev/null & sleep 60; sudo pkill -f bpftrace

Record a quick fio baseline (change device or mountpoint to match reality):

fio --name=randread --filename=/mnt/data/testfile --size=2G \
    --bs=4k --iodepth=32 --rw=randread --direct=1 --numjobs=1 \
    --runtime=60 --time_based --group_reporting > /var/log/ai-fs/fio.txt

Pro tip: capture at multiple times (e.g., morning/noon/evening) to let the model learn daily patterns.


2) Build a “heat map” of files and train a tiny model

Extract “hot” files by recency and churn using find; save as CSV:

# Walk a target tree; adjust path
BASE=/srv/appdata
find "$BASE" -xdev -type f -printf '%A@,%T@,%s,%p\n' \
  | awk -F, 'BEGIN{OFS=","}{atime=$1; mtime=$2; size=$3; path=$4; print atime,mtime,size,path}' \
  > /var/log/ai-fs/file_stats.csv

Create a Python virtual environment and install minimal ML deps:

python3 -m venv ~/.venvs/ai-fs && source ~/.venvs/ai-fs/bin/activate
pip install --upgrade pip
pip install pandas scikit-learn numpy

Analyse: cluster time windows by load and flag hot directories.

#!/usr/bin/env python3
import pandas as pd, numpy as np, re
from sklearn.cluster import KMeans
from sklearn.ensemble import IsolationForest
from pathlib import Path
from datetime import datetime

log = Path("/var/log/ai-fs")

# Parse iostat device util% by timestamp-ish line order
util = []
with open(log/"iostat.txt") as f:
    ts = 0
    for line in f:
        parts = line.split()
        if len(parts) > 11 and parts[0] not in ("Device", "Linux"):
            # columns vary; util is typically the last column
            try:
                util.append({"sample": ts, "dev": parts[0], "util": float(parts[-1])})
            except:
                pass
        if line.strip() == "":
            ts += 1
util_df = pd.DataFrame(util)
if util_df.empty:
    raise SystemExit("No iostat data parsed")

# Aggregate util by sample
w = util_df.groupby("sample")["util"].mean().to_frame("util")

# Load file stats
fs = pd.read_csv(log/"file_stats.csv", names=["atime","mtime","size","path"])
now = datetime.now().timestamp()
fs["age_days"] = (now - fs["atime"]) / 86400
fs["hot_score"] = (1/(1+fs["age_days"])) * np.log10(1+fs["size"])

# Summarise by top-level dir under BASE (second path segment)
def topdir(p):
    parts = Path(p).parts
    return "/".join(parts[:3]) if len(parts) >= 3 else str(Path(p).parent)
fs["topdir"] = fs["path"].apply(topdir)
dir_hot = fs.groupby("topdir")["hot_score"].sum().sort_values(ascending=False).head(10)

# Cluster samples into low/med/high util
k = KMeans(n_clusters=3, n_init="auto").fit(w[["util"]])
w["cluster"] = k.labels_
clabels = {int(i): f"cluster{i}" for i in sorted(set(k.labels_))}
summary = w.groupby("cluster")["util"].agg(["count","mean","max"]).sort_values("mean")

print("\nTop hot directories by hot_score:")
print(dir_hot.to_string())

print("\nI/O Util clusters:")
print(summary.to_string())

# Detect outlier periods (latency spikes if we had latency; here use util as proxy)
iso = IsolationForest(contamination=0.1, random_state=0).fit(w[["util"]])
w["outlier"] = iso.predict(w[["util"]])
spikes = w[w["outlier"] == -1]
print(f"\nDetected {len(spikes)} anomalous high-util samples (investigate scheduling).")

What you get:

  • A ranked list of hot directories to optimise or relocate.

  • Clustered “load levels” to time your maintenance and batch work.

  • Anomalous windows hinting at contention or device issues.


3) Apply safe, high-impact file system and I/O tunables

Make small, reversible changes. Measure before/after with fio or your app’s own SLOs.

  • Use relatime or noatime where atime isn’t needed

    • relatime is default and safe. Consider noatime only for read-heavy trees where atime is irrelevant (e.g., caches).
    • Example remount:
    sudo mount -o remount,relatime /mnt/data
    # or, for a specific bind-mount of a cache dir:
    echo '/srv/appdata/cache /srv/appdata/cache none bind,noatime 0 0' | sudo tee -a /etc/fstab
    
  • Right-size readahead (bigger for sequential, smaller for random)

    DEV=/dev/nvme0n1
    sudo blockdev --getra $DEV         # current in 512B sectors
    sudo blockdev --setra 4096 $DEV    # example: ~2MB readahead
    

    Test with fio sequential reads to confirm improvement.

  • Choose an appropriate I/O scheduler

    • Check options:
    DEV=nvme0n1
    cat /sys/block/$DEV/queue/scheduler
    
    • Guidelines (modern multi-queue):
    • NVMe SSD: mq-deadline or none (check kernel/docs; none may be default on NVMe)
    • SATA SSD: mq-deadline is a solid default
    • HDD: bfq can improve interactive workloads; mq-deadline often good for throughput
    • Temporary change:
    echo mq-deadline | sudo tee /sys/block/$DEV/queue/scheduler
    

    Persist via udev rules or kernel command line as appropriate.

  • Trim SSDs regularly

    sudo systemctl enable --now fstrim.timer
    sudo systemctl status fstrim.timer
    
  • Filesystem-aware tweaks (conservative)

    • ext4 and xfs defaults are reasonable on modern distros. Avoid disabling write barriers or journaling modes that risk data loss.
    • Confirm mount options:
    findmnt -o TARGET,FSTYPE,OPTIONS /mnt/data
    

4) Smarter data placement and compression (based on the model)

Use your hot directory list to place data on the right media and compress cold data.

  • Move hot paths to faster storage (NVMe) and cold paths to capacity disks

    # Example: move a hot dir to an NVMe-backed mount and bind it in place
    sudo rsync -aXS --info=progress2 /srv/appdata/hotdir/ /nvme_pool/hotdir/
    sudo mv /srv/appdata/hotdir /srv/appdata/hotdir.bak
    sudo mkdir -p /srv/appdata/hotdir
    echo '/nvme_pool/hotdir /srv/appdata/hotdir none bind 0 0' | sudo tee -a /etc/fstab
    sudo mount -a && sudo rm -rf /srv/appdata/hotdir.bak
    
  • Transparent compression (if your FS supports it)

    • btrfs:
    # Add compress=zstd:3 and optionally autodefrag for mixed workloads
    echo 'UUID=<uuid> /data btrfs defaults,compress=zstd:3 0 0' | sudo tee -a /etc/fstab
    sudo mount -o remount /data
    
    • ZFS:
    sudo zfs set compression=zstd pool/dataset
    
    • ext4/xfs do not offer native transparent compression; consider using btrfs/ZFS for cold archives if compression matters.
  • Example “cold file” migration policy (30+ days old):

    find /srv/appdata -xdev -type f -mtime +30 -size +10M -print0 \
    | rsync -0a --remove-source-files --files-from=- /srv/appdata/ /slow_pool/cold/
    

Always re-measure after moves; seek-heavy hot sets belong on low-latency devices.


5) Close the loop: automate, monitor, and rollback safely

  • Schedule collection and analysis

    # /etc/cron.d/ai-fs
    */30 * * * * root iostat -dxm 10 1 >> /var/log/ai-fs/iostat.txt
    5 0 * * *   root /usr/local/bin/ai-fs-analyse.sh
    
  • Keep changes small and logged

    • Apply one tweak per change window.
    • Store before/after fio and app latency percentiles.
    • Roll back quickly (e.g., remount options, readahead, scheduler are one-liners).
  • Watch device health

    sudo smartctl -a /dev/sda | egrep 'Reallocated|Pending|Media_Wearout'
    sudo nvme smart-log /dev/nvme0
    

A quick, real-world-style scenario

A mail server shows midday latency spikes. Telemetry clusters reveal a “high util” window around 11:30–13:00. Hot directory analysis points at the mail queue and index DBs under /var/spool/postfix and /var/lib/dovecot. Actions:

  • Move these hot directories to NVMe via bind mounts.

  • Set mq-deadline on NVMe, enable fstrim.timer.

  • Increase readahead for the HDD where cold archives live.

  • Keep relatime; avoid noatime on directories used by backup tools needing atime. Result: p95 message delivery latency drops from 750 ms to 210 ms during the peak window, confirmed by before/after metrics and fio sanity checks.


Common pitfalls to avoid

  • Turning off write barriers or forcing unsafe journaling modes for marginal gains.

  • Global noatime on paths where tools rely on access time.

  • Oversized readahead on random I/O workloads (it can hurt).

  • Ignoring device health—no amount of tuning fixes a failing SSD.


Conclusion and next steps

AI won’t replace your instincts—it amplifies them. With a few Bash commands and a small Python script, you can:

  • See your storage patterns clearly,

  • Optimise the highest-impact paths and windows,

  • Iterate safely with evidence.

Your next step: 1) Install the prerequisites, run the telemetry collector, and generate your first hot directory list. 2) Make one safe change (scheduler, readahead, or a targeted bind mount). 3) Re-measure and document results. Repeat.

If you want a ready-made toolkit, package your scripts into a repo and add a systemd timer for daily analysis. Have fun turning your disks into a competitive advantage—guided by your own data.