HDD/SSD Speedtest Linux

Ich habe mich an einem kleinen Python Skript versucht, um die Schreib- und Lesegeschwindigkeit
der im System vorhandenen Mountpunkte und dem Benutzerverzeichnis zu ermitteln.

Falls wer Interesse und/oder Zeit hat, es mal bei sich zu testen.

Code:
import sys
import subprocess
import os
import time
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QComboBox, QPushButton, QTextEdit

def get_mount_points_from_fstab(fstab_path):
    mount_points = []
    with open(fstab_path, 'r') as fstab_file:
        for line in fstab_file:
            line = line.strip()
            if line and not line.startswith('#'):
                tokens = line.split()
                if len(tokens) >= 2:
                    mount_point = tokens[1]
                    if mount_point.startswith("/"):
                        mount_points.append(mount_point)
    return mount_points

class DD_GUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("HDD/SSD Speedtest")

        self.initUI()

    def initUI(self):
        self.file_sizes = ["4G", "8G", "16G"]

        self.dateigroesse_label = QLabel("Dateigröße:", self)
        self.dateigroesse_label.move(10, 10)
        self.dateigroesse_combobox = QComboBox(self)
        self.dateigroesse_combobox.addItems(self.file_sizes)
        self.dateigroesse_combobox.move(100, 10)

        self.durchlaeufe_label = QLabel("Durchläufe:", self)
        self.durchlaeufe_label.move(10, 40)
        self.durchlaeufe_combobox = QComboBox(self)
        self.durchlaeufe_combobox.addItems([str(i) for i in range(1, 11)])
        self.durchlaeufe_combobox.move(100, 40)

        self.mountpoint_label = QLabel("Mountpunkt:", self)
        self.mountpoint_label.move(10, 70)

        home_dir = os.path.expanduser("~")
        mount_points = get_mount_points_from_fstab('/etc/fstab')
        mount_points.append(home_dir)  # Füge das Home-Verzeichnis hinzu
        self.mountpoint_combobox = QComboBox(self)
        self.mountpoint_combobox.addItems(mount_points)
        self.mountpoint_combobox.move(100, 70)

        self.start_button = QPushButton("Start", self)
        self.start_button.move(280, 100)
        self.start_button.clicked.connect(self.start_dd)

        self.output_text = QTextEdit(self)
        self.output_text.setReadOnly(True)
        self.output_text.setGeometry(10, 130, 380, 150)

        self.setGeometry(100, 100, 400, 300)

    def start_dd(self):
        file_size = self.dateigroesse_combobox.currentText()
        durchlaeufe = self.durchlaeufe_combobox.currentText()
        mount_point = self.mountpoint_combobox.currentText()

        output_file = os.path.join(mount_point, "test")

        # Schreiben der Datei
        write_command = f"dd if=/dev/zero of={output_file} bs={file_size} count={durchlaeufe} iflag=fullblock 2>&1"
        write_process = subprocess.Popen(write_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        self.update_output_text("schreiben...", mount_point)
        for line in write_process.stdout:
            self.update_output_text(line.strip(), mount_point)
        for line in write_process.stderr:
            self.update_output_text(line.strip(), mount_point)
        write_process.wait()

        # Lesen der Datei
        read_command = f"dd if={output_file} of=/dev/null bs={file_size} count={durchlaeufe} iflag=fullblock 2>&1"
        read_process = subprocess.Popen(read_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        self.update_output_text("lesen...", mount_point)
        time.sleep(1)  # Eine kurze Pause, um sicherzustellen, dass das Schreiben abgeschlossen ist, bevor das Lesen beginnt
        for line in read_process.stdout:
            self.update_output_text(line.strip(), mount_point)
        for line in read_process.stderr:
            self.update_output_text(line.strip(), mount_point)
        read_process.wait()

        # Löschen der Datei
        if os.path.exists(output_file):
            os.remove(output_file)

    def update_output_text(self, text, mount_point=None):
        if mount_point:
            text = f"{mount_point}: {text}"
        relevant_lines = [
            "bytes",  # Nur Zeilen, die "bytes" enthalten, anzeigen
            "copied",
            "s,"
        ]
        for line in text.split('\n'):
            if any(keyword in line for keyword in relevant_lines):
                self.output_text.append(line)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = DD_GUI()
    window.show()
    sys.exit(app.exec_())
 
Warum nimmst du nicht fio(1)?
 
  • Gefällt mir
Reaktionen: guzzisti und 0x8100
abgesehen von #2:
  • du erstellst/löscht hart eine "test" datei. was ist, wenn ich die schon habe und die mir wichtig ist? für (unique) temporäre dateien gibt es tempfile
  • du nutzt dd mit if=/dev/zero -> wenn man da z.b. auf ein komprimierendes dateisystem wie z.b. btrfs schreibt lassen sich die ganzen nullen wunderbar packen und es werden wohl werte rauskommen, die nichts mit der realität zu tun haben.
 
  • Gefällt mir
Reaktionen: oicfar, cbtaste420, andy_m4 und 2 andere
Jetzt mit tempfile.

Code:
import sys
import subprocess
import os
import time
import tempfile
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QComboBox, QPushButton, QTextEdit

def get_mount_points_from_fstab(fstab_path):
    mount_points = []
    with open(fstab_path, 'r') as fstab_file:
        for line in fstab_file:
            line = line.strip()
            if line and not line.startswith('#'):
                tokens = line.split()
                if len(tokens) >= 2:
                    mount_point = tokens[1]
                    if mount_point.startswith("/"):
                        mount_points.append(mount_point)
    return mount_points

class DD_GUI(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("HDD/SSD Speedtest")
        self.initUI()

    def initUI(self):
        self.file_sizes = ["4G", "8G", "16G"]

        self.dateigroesse_label = QLabel("Dateigröße:", self)
        self.dateigroesse_label.move(10, 10)
        self.dateigroesse_combobox = QComboBox(self)
        self.dateigroesse_combobox.addItems(self.file_sizes)
        self.dateigroesse_combobox.move(100, 10)

        self.durchlaeufe_label = QLabel("Durchläufe:", self)
        self.durchlaeufe_label.move(10, 40)
        self.durchlaeufe_combobox = QComboBox(self)
        self.durchlaeufe_combobox.addItems([str(i) for i in range(1, 11)])
        self.durchlaeufe_combobox.move(100, 40)

        self.mountpoint_label = QLabel("Mountpunkt:", self)
        self.mountpoint_label.move(10, 70)

        home_dir = os.path.expanduser("~")
        mount_points = get_mount_points_from_fstab('/etc/fstab')
        mount_points.append(home_dir)  # Füge das Home-Verzeichnis hinzu
        self.mountpoint_combobox = QComboBox(self)
        self.mountpoint_combobox.addItems(mount_points)
        self.mountpoint_combobox.move(100, 70)

        self.start_button = QPushButton("Start", self)
        self.start_button.move(280, 100)
        self.start_button.clicked.connect(self.start_benchmark)

        self.output_text = QTextEdit(self)
        self.output_text.setReadOnly(True)
        self.output_text.setGeometry(10, 130, 380, 150)

        self.setGeometry(100, 100, 400, 300)

    def start_benchmark(self):
        file_size = self.dateigroesse_combobox.currentText()
        durchlaeufe = self.durchlaeufe_combobox.currentText()
        mount_point = self.mountpoint_combobox.currentText()

        with tempfile.NamedTemporaryFile(delete=False) as temp_file:
            temp_file_path = temp_file.name

        self.create_test_file(temp_file_path, file_size, durchlaeufe, mount_point)
        self.start_dd(temp_file_path, file_size, durchlaeufe, mount_point)
        os.remove(temp_file_path)

    def create_test_file(self, output_file, file_size, durchlaeufe, mount_point):
        # Erstellen der Testdatei mit /dev/random
        write_command = f"dd if=/dev/zero of={output_file} bs={file_size} count={durchlaeufe} iflag=fullblock 2>&1"
        write_process = subprocess.Popen(write_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        self.update_output_text("Testdatei wird erstellt...", mount_point)
        for line in write_process.stdout:
            self.update_output_text(line.strip(), mount_point)
        for line in write_process.stderr:
            self.update_output_text(line.strip(), mount_point)
        write_process.wait()

    def start_dd(self, output_file, file_size, durchlaeufe, mount_point):
        # Lesen der Testdatei mit /dev/random
        read_command = f"dd if={output_file} of=/dev/null bs={file_size} count={durchlaeufe} iflag=fullblock 2>&1"
        read_process = subprocess.Popen(read_command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        self.update_output_text("Testdatei wird gelesen...", mount_point)
        time.sleep(1)  # Eine kurze Pause, um sicherzustellen, dass das Schreiben abgeschlossen ist, bevor das Lesen beginnt
        for line in read_process.stdout:
            self.update_output_text(line.strip(), mount_point)
        for line in read_process.stderr:
            self.update_output_text(line.strip(), mount_point)
        read_process.wait()

    def update_output_text(self, text, mount_point=None):
        if mount_point:
            text = f"{mount_point}: {text}"
        relevant_lines = [
            "bytes",  # Nur Zeilen, die "bytes" enthalten, anzeigen
            "copied",
            "s,"
        ]
        for line in text.split('\n'):
            if any(keyword in line for keyword in relevant_lines):
                index = line.rfind("s,")  # Finde die Position des letzten "s,"
                if index != -1:
                    line = line[index + 2:]  # Beginne nach dem letzten "s," zu schneiden
                self.output_text.append(line.strip())

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = DD_GUI()
    window.show()
    sys.exit(app.exec_())
 
Ein Speedtest mit Python. Feinsinniger Humor muss ich sagen. :-)
 
andy_m4 schrieb:
Ein Speedtest mit Python. Feinsinniger Humor muss ich sagen. :-)
Für die Bell and Whistles drumrum sehe ich den Witz nicht.

Wenn man mit fio testen würde könnte man noch viel mehr Bell and Whistles machen.
 
Zuletzt bearbeitet:
Du hast aber schon gemerkt, dass der eigentliche Test nichts mit Python zu tun hat? :watt:
 
Cachebehandlung?
bs=16G?
Warum dd? Was stimmt nicht mit der Python API?
Wenn ja, warum kein Bashscript?
 
Für einen Speedtest mit fio ist mir mal folgendes Script untergekommen, das den CrytalSpeedMark imitiert:

Code:
#!/bin/bash
#############################################################################################################
#Changelog                                                                                                  #
#############################################################################################################
#Added prompts for user input to configure script instead of relying on hardcoded settings.
#Added a lot of errorchecking
#The script is now optionally compatible with dash (this is the reason for there being a sed command at the end of every echo -e instance, dash liked to print the -e part when I was testing.)
#Vastly improved compatibility across distributions
#Special thanks to everyone who contributed here: https://gist.github.com/i3v/99f8ef6c757a5b8e9046b8a47f3a9d5b
#Also extra special thanks to BAGELreflex on github for this: https://gist.github.com/BAGELreflex/c04e7a25d64e989cbd9376a9134b8f6d it made a huge difference to this improved version.
#Added optimizations for 512k and 4k tests (they now use QSIZE instead of SIZE, it makes these tests a lot faster and doesn't affect accuracy much, assuming SIZE is appropriately configured for your drive.)
#Added option to not use legacy (512k and Q1T1 Seq R/W tests) to save time when testing.
#Ensured the script can run fine without df installed now. Some information may be missing but worst case scenario it'll just look ugly.
#Added a save results option that imitates the saved results from crystaldiskmark; the formatting is a little wonky but it checks out. Great for comparing results between operating systems.
#Reconfigured results to use MegaBytes instead of MebiBytes (This is what crystaldiskmark uses so results should now be marginally closer).
#Sequential read/write results (512k, q1t1 seq and q32t1 seq) will now appear as soon as they're finished and can be viewed while the 4k tests are running.
#Note: The legacy test option defaults to no if nothing is selected, the result saving defaults to yes. It's easy to change if you don't like this.
#Observation: When testing, I observed that the read results seemed mostly consistent with the results I got from crystaldiskmark on windows, however there's something off with the write results.
#Sorry for the messy code :)
#############################################################################################################
#User input requests and error checking                                                                     #
#############################################################################################################
if [ -f /usr/bin/fio ]; then #Dependency check
    :
else
    echo -e "\033[1;31mError: This script requires fio to run, please make sure it is installed." | sed 's:-e::g'
    exit
fi

if [ -f /usr/bin/df ]; then #Dependency check
    nodf=0
else
    nodf=1
    echo -e "\033[1;31mWarning: df is not installed, this script relies on df to display certain information, some information may be missing." | sed 's:-e::g'
fi

if [ "$(ps -ocmd= | tail -1)" = "bash" ]; then
    echo "What drive do you want to test? (Default: $HOME on /dev/$(df $HOME | grep /dev | cut -d/ -f3 | cut -d" " -f1) )"
    echo -e "\033[0;33mOnly directory paths (e.g. /home/user/) are valid targets.\033[0;00m"
    read -e TARGET
else #no autocomplete available for dash.
    echo "What drive do you want to test? (Default: $HOME on /dev/$(df $HOME | grep /dev | cut -d/ -f3 | cut -d" " -f1) )"
    echo -e "\033[0;33mOnly directory paths (e.g. /home/user/) are valid targets. Use bash if you want autocomplete.\033[0;00m" | sed 's:-e::g'
    read TARGET
fi

echo "
How many times to run the test? (Default: 5)"
read LOOPS

echo "How large should each test be in MiB? (Default: 1024)"
echo -e "\033[0;33mOnly multiples of 32 are permitted!\033[0;00m" | sed 's:-e::g'

read SIZE

echo "Do you want to write only zeroes to your test files to imitate dd benchmarks? (Default: 0)"
echo -e "\033[0;33mEnabling this setting may drastically alter your results, not recommended unless you know what you're doing.\033[0;00m" | sed 's:-e::g'
read WRITEZERO

echo "Would you like to include legacy tests (512kb & Q1T1 Sequential Read/Write)? [Y/N]"
read LEGACY

if [ -z $TARGET ]; then
    TARGET=$HOME
elif [ -d $TARGET ]; then
    :
else
    echo -e "\033[1;31mError: $TARGET is not a valid path."
    exit
fi

if [ -z $LOOPS ]; then
    LOOPS=5
elif [ "$LOOPS" -eq "$LOOPS" ] 2>/dev/null; then
    :
else
  echo -e "\033[1;31mError: $LOOPS is not a valid number, please use a number to declare how many times to loop tests." | sed 's:-e::g'
  exit
fi

if [ -z $SIZE ]; then
    SIZE=1024
elif [ "$SIZE" -eq "$SIZE" ] 2>/dev/null && ! (( $SIZE % 32 )) 2>/dev/null;then
    :
else
    echo -e "\033[1;31mError: The test size must be an integer set to a multiple of 32. Please write a multiple of 32 for the size setting (Optimal settings: 1024, 2048, 4096, 8192, 16384)."
    exit
fi

if [ -z $WRITEZERO ]; then
    WRITEZERO=0
elif [ "$WRITEZERO" -eq 1 ] 2>/dev/null || [ "$WRITEZERO" -eq 0 ] 2>/dev/null; then
    :
else
    echo -e "\033[1;31mError: WRITEZERO only accepts 0 or 1, $WRITEZERO is not a valid argument." | sed 's:-e::g'
    exit
fi

if [ "$LEGACY" = "Y" ] || [ "$LEGACY" = "y" ]; then
    :
else
    LEGACY=no
fi

if [ $nodf = 1 ]; then
    echo "
    Settings are as follows:
    Target Directory: $TARGET
    Size Of Test: $SIZE MiB
    Number Of Loops: $LOOPS
    Write Zeroes: $WRITEZERO
    Legacy Tests: $LEGACY
    "
    echo "Are you sure these are correct? [Y/N]"
    read REPLY
    if [ $REPLY = Y ] || [ $REPLY = y ]; then
        REPLY=""
    else
        echo ""
        exit
    fi

else
    DRIVE=$(df $TARGET | grep /dev | cut -d/ -f3 | cut -d" " -f1 | rev | cut -c 2- | rev)

    if [ "$(echo $DRIVE | cut -c -4)" = "nvme" ]; then #NVME Compatibility
        echo $DRIVE
        DRIVE=$(df $TARGET | grep /dev | cut -d/ -f3 | cut -d" " -f1 | rev | cut -c 3- | rev)
        echo $DRIVE
    fi
    DRIVEMODEL=$(cat /sys/block/$DRIVE/device/model | sed 's/ *$//g')
    DRIVESIZE=$(($(cat /sys/block/$DRIVE/size)*512/1024/1024/1024))GB
    DRIVEPERCENT=$(df -h $TARGET | cut -d ' ' -f11 | tail -n 1)
    DRIVEUSED=$(df -h $TARGET | cut -d ' ' -f6 | tail -n 1)

    echo "
    Settings are as follows:
    Target Directory: $TARGET
    Target Drive: $DRIVE
    Size Of Test: $SIZE MiB
    Number Of Loops: $LOOPS
    Write Zeroes: $WRITEZERO
    Legacy Tests: $LEGACY
    "
    echo "Are you sure these are correct? [Y/N]"
    read REPLY
    if [ "$REPLY" = "Y" ] || [ "$REPLY" = "y" ]; then
        REPLY=""
    else
        echo ""
        exit
    fi
fi
#############################################################################################################
#Setting the last Variables And Running Sequential R/W Benchmarks                                           #
#############################################################################################################


QSIZE=$(($SIZE / 32)) #Size of Q32Seq tests
SIZE=$(echo $SIZE)m
QSIZE=$(echo $QSIZE)m

if [ $nodf = 1 ]; then
    echo "
Running Benchmark,  please wait...
    "
else
    echo "
Running Benchmark on: /dev/$DRIVE, $DRIVEMODEL ($DRIVESIZE), please wait...
"
fi

if [ $LEGACY = Y ] || [ $LEGACY = y ]; then
    fio --loops=$LOOPS --size=$SIZE --filename="$TARGET/.fiomark.tmp" --stonewall --ioengine=libaio --direct=1 --zero_buffers=$WRITEZERO --output-format=json \
  --name=Bufread --loops=1 --bs=$SIZE --iodepth=1 --numjobs=1 --rw=readwrite \
  --name=Seqread --bs=$SIZE --iodepth=1 --numjobs=1 --rw=read \
  --name=Seqwrite --bs=$SIZE --iodepth=1 --numjobs=1 --rw=write \
  --name=SeqQ32T1read --bs=$QSIZE --iodepth=32 --numjobs=1 --rw=read \
  --name=SeqQ32T1write --bs=$QSIZE --iodepth=32 --numjobs=1 --rw=write \
  > "$TARGET/.fiomark.txt"

    fio --loops=$LOOPS --size=$QSIZE --filename="$TARGET/.fiomark-512k.tmp" --stonewall --ioengine=libaio --direct=1 --zero_buffers=$WRITEZERO --output-format=json \
  --name=512kread --bs=512k --iodepth=1 --numjobs=1 --rw=read \
  --name=512kwrite --bs=512k --iodepth=1 --numjobs=1 --rw=write \
  > "$TARGET/.fiomark-512k.txt"

    SEQR="$(($(cat "$TARGET/.fiomark.txt" | grep -A15 '"name" : "Seqread"' | grep bw | grep -v '_' | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark.txt" | grep -A15 '"name" : "Seqread"' | grep -m1 iops | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
    SEQW="$(($(cat "$TARGET/.fiomark.txt" | grep -A80 '"name" : "Seqwrite"' | grep bw | grep -v '_' | sed 2\!d | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark.txt" | grep -A80 '"name" : "Seqwrite"' | grep iops | sed '7!d' | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
    F12KR="$(($(cat "$TARGET/.fiomark-512k.txt" | grep -A15 '"name" : "512kread"' | grep bw | grep -v '_' | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark-512k.txt" | grep -A15 '"name" : "512kread"' | grep -m1 iops | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
    F12KW="$(($(cat "$TARGET/.fiomark-512k.txt" | grep -A80 '"name" : "512kwrite"' | grep bw | grep -v '_' | sed 2\!d | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark-512k.txt" | grep -A80 '"name" : "512kwrite"' | grep iops | sed '7!d' | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
    SEQ32R="$(($(cat "$TARGET/.fiomark.txt" | grep -A15 '"name" : "SeqQ32T1read"' | grep bw | grep -v '_' | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark.txt" | grep -A15 '"name" : "SeqQ32T1read"' | grep -m1 iops | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
    SEQ32W="$(($(cat "$TARGET/.fiomark.txt" | grep -A80 '"name" : "SeqQ32T1write"' | grep bw | grep -v '_' | sed 2\!d | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark.txt" | grep -A80 '"name" : "SeqQ32T1write"' | grep iops | sed '7!d' | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"

    echo -e "
Results:
\033[0;33m
Sequential Read: $SEQR
Sequential Write: $SEQW
\033[0;32m
512KB Read: $F12KR
512KB Write: $F12KW
\033[1;36m
Sequential Q32T1 Read: $SEQ32R
Sequential Q32T1 Write: $SEQ32W" | sed 's:-e::g'

else
    fio --loops=$LOOPS --size=$SIZE --filename="$TARGET/.fiomark.tmp" --stonewall --ioengine=libaio --direct=1 --zero_buffers=$WRITEZERO --output-format=json \
  --name=Bufread --loops=1 --bs=$SIZE --iodepth=1 --numjobs=1 --rw=readwrite \
  --name=SeqQ32T1read --bs=$QSIZE --iodepth=32 --numjobs=1 --rw=read \
  --name=SeqQ32T1write --bs=$QSIZE --iodepth=32 --numjobs=1 --rw=write \
  > "$TARGET/.fiomark.txt"

    SEQ32R="$(($(cat "$TARGET/.fiomark.txt" | grep -A15 '"name" : "SeqQ32T1read"' | grep bw | grep -v '_' | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark.txt" | grep -A15 '"name" : "SeqQ32T1read"' | grep -m1 iops | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
    SEQ32W="$(($(cat "$TARGET/.fiomark.txt" | grep -A80 '"name" : "SeqQ32T1write"' | grep bw | grep -v '_' | sed 2\!d | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark.txt" | grep -A80 '"name" : "SeqQ32T1write"' | grep iops | sed '7!d' | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"

    echo -e "
Results:
\033[1;36m
Sequential Q32T1 Read: $SEQ32R
Sequential Q32T1 Write: $SEQ32W" | sed 's:-e::g'
fi

#############################################################################################################
#4KiB Tests & Results                                                                                       #
#############################################################################################################

fio --loops=$LOOPS --size=$QSIZE --filename="$TARGET/.fiomark-4k.tmp" --stonewall --ioengine=libaio --direct=1 --zero_buffers=$WRITEZERO --output-format=json \
  --name=4kread --bs=4k --iodepth=1 --numjobs=1 --rw=randread \
  --name=4kwrite --bs=4k --iodepth=1 --numjobs=1 --rw=randwrite \
  --name=4kQ32T1read --bs=4k --iodepth=32 --numjobs=1 --rw=randread \
  --name=4kQ32T1write --bs=4k --iodepth=32 --numjobs=1 --rw=randwrite \
  --name=4kQ8T8read --bs=4k --iodepth=8 --numjobs=8 --rw=randread \
  --name=4kQ8T8write --bs=4k --iodepth=8 --numjobs=8 --rw=randwrite \
  > "$TARGET/.fiomark-4k.txt"

FKR="$(($(cat "$TARGET/.fiomark-4k.txt" | grep -A15 '"name" : "4kread"' | grep bw | grep -v '_' | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark-4k.txt" | grep -A15 '"name" : "4kread"' | grep -m1 iops | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
FKW="$(($(cat "$TARGET/.fiomark-4k.txt" | grep -A80 '"name" : "4kwrite"' | grep bw | grep -v '_' | sed 2\!d | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark-4k.txt" | grep -A80 '"name" : "4kwrite"' | grep iops | sed '7!d' | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
FK32R="$(($(cat "$TARGET/.fiomark-4k.txt" | grep -A15 '"name" : "4kQ32T1read"' | grep bw | grep -v '_' | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark-4k.txt" | grep -A15 '"name" : "4kQ32T1read"' | grep -m1 iops | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
FK32W="$(($(cat "$TARGET/.fiomark-4k.txt" | grep -A80 '"name" : "4kQ32T1write"' | grep bw | grep -v '_' | sed 2\!d | cut -d: -f2 | sed s:,::g)/1000))MB/s [   $(cat "$TARGET/.fiomark-4k.txt" | grep -A80 '"name" : "4kQ32T1write"' | grep iops | sed '7!d' | cut -d: -f2 | cut -d. -f1 | sed 's: ::g') IOPS]"
FK8R="$(($(cat "$TARGET/.fiomark-4k.txt" | grep -A15 '"name" : "4kQ8T8read"' | grep bw | grep -v '_' | sed 's/        "bw" : //g' | sed 's:,::g' | awk '{ SUM += $1} END { print SUM }')/1000))MB/s [   $(cat "$TARGET/.fiomark-4k.txt" | grep -A15 '"name" : "4kQ8T8read"' | grep iops | sed 's/        "iops" : //g' | sed 's:,::g' | awk '{ SUM += $1} END { print SUM }' | cut -d. -f1) IOPS]"
FK8W="$(($(cat "$TARGET/.fiomark-4k.txt" | grep -A80 '"name" : "4kQ8T8write"' | grep bw | sed 's/        "bw" : //g' | sed 's:,::g' | awk '{ SUM += $1} END { print SUM }')/1000))MB/s [   $(cat "$TARGET/.fiomark-4k.txt" | grep -A80 '"name" : "4kQ8T8write"' | grep '"iops" '| sed 's/        "iops" : //g' | sed 's:,::g' | awk '{ SUM += $1} END { print SUM }' | cut -d. -f1) IOPS]"

echo -e "\033[1;35m
4KB Q8T8 Read: $FK8R
4KB Q8T8 Write: $FK8W
\033[1;33m
4KB Q32T1 Read: $FK32R
4KB Q32T1 Write: $FK32W
\033[0;36m
4KB Read: $FKR
4KB Write: $FKW
\033[0m
" | sed 's:-e::g'

echo "Would you like to save these results? [Y/N]"
read REPLY
if [ "$REPLY" = "N" ] || [ "$REPLY" = "n" ]; then
    REPLY=""
else
    DRIVESIZE=$(df -h $TARGET | cut -d ' ' -f3 | tail -n 1)
    echo "
Saving at $HOME/$DRIVE$(date +%F%I%M%S).txt
"
    if [ "$LEGACY" = "Y" ] || [ "$LEGACY" = "y" ]; then
echo "-----------------------------------------------------------------------
Flexible I/O Tester - $(fio --version) (C) axboe
                          Fio Github : https://github.com/axboe/fio
                       Script Source : https://unix.stackexchange.com/a/480191/72554
-----------------------------------------------------------------------
* MB/s = 1,000,000 bytes/s
* KB = 1000 bytes, KiB = 1024 bytes

   Legacy Seq Read (Q=  1,T= 1) :   $SEQR
  Legacy Seq Write (Q=  1,T= 1) :   $SEQW
   512KiB Seq Read (Q=  1,T= 1) :   $F12KR
  512KiB Seq Write (Q=  1,T= 1) :   $F12KW
   Sequential Read (Q= 32,T= 1) :   $SEQ32R
  Sequential Write (Q= 32,T= 1) :   $SEQ32W
  Random Read 4KiB (Q=  8,T= 8) :   $FK8R
 Random Write 4KiB (Q=  8,T= 8) :   $FK8W
  Random Read 4KiB (Q= 32,T= 1) :   $FK32R
 Random Write 4KiB (Q= 32,T= 1) :   $FK32W
  Random Read 4KiB (Q=  1,T= 1) :   $FKR
 Random Write 4KiB (Q=  1,T= 1) :   $FKW

  Test : $(echo $SIZE | rev | cut -c 2- | rev) MiB [$DRIVEMODEL, $DRIVE $DRIVEPERCENT ($(echo $DRIVEUSED | rev | cut -c 2- | rev)/$(echo $DRIVESIZE | rev | cut -c 2- | rev) GiB] (x$LOOPS)  [Interval=0 sec]
  Date : $(date +%F | sed 's:-:/:g') $(date +%T)
    OS : $(uname -srm)
  " > "$HOME/$DRIVE$(date +%F%I%M%S).txt"
    else
echo "-----------------------------------------------------------------------
Flexible I/O Tester - $(fio --version) (C) axboe
                          Fio Github : https://github.com/axboe/fio
                       Script Source : https://unix.stackexchange.com/a/480191/72554
-----------------------------------------------------------------------
* MB/s = 1,000,000 bytes/s
* KB = 1000 bytes, KiB = 1024 bytes

   Sequential Read (Q= 32,T= 1) :   $SEQ32R
  Sequential Write (Q= 32,T= 1) :   $SEQ32W
  Random Read 4KiB (Q=  8,T= 8) :   $FK8R
 Random Write 4KiB (Q=  8,T= 8) :   $FK8W
  Random Read 4KiB (Q= 32,T= 1) :   $FK32R
 Random Write 4KiB (Q= 32,T= 1) :   $FK32W
  Random Read 4KiB (Q=  1,T= 1) :   $FKR
 Random Write 4KiB (Q=  1,T= 1) :   $FKW

  Test : $(echo $SIZE | rev | cut -c 2- | rev) MiB [$DRIVEMODEL, $DRIVE $DRIVEPERCENT ($(echo $DRIVEUSED | rev | cut -c 2- | rev)/$(echo $DRIVESIZE | rev | cut -c 2- | rev) GiB] (x$LOOPS)  [Interval=0 sec]
  Date : $(date +%F | sed 's:-:/:g') $(date +%T)
    OS : $(uname -srm)
  " > "$HOME/$DRIVE$(date +%F%I%M%S).txt"
    fi
fi


rm "$TARGET/.fiomark.txt" "$TARGET/.fiomark-512k.txt" "$TARGET/.fiomark-4k.txt" 2>/dev/null
rm "$TARGET/.fiomark.tmp" "$TARGET/.fiomark-512k.tmp" "$TARGET/.fiomark-4k.tmp" 2>/dev/null
 

Ähnliche Themen

Zurück
Oben