UNIXwork

C: Attribute von allen Dateien im Verzeichnis

2016-12-23 21:06:16.0

Wenn man ein Verzeichnis liest und von allen enthaltenen Dateien die Extended Attributes erhalten will, gibt es zwei Möglichkeiten:

  1. Man fügt zum Verzeichnispfad den Dateinamen hinzu und nutzt den neu erhaltenen Pfad mit den Syscalls listxattr oder getxattr.
  2. Mit dem Filedescriptor des Verzeichnisses und openat öffnet man die Dateien und nutzt dann flistxattr und getxattr.

Ich hab mich gefragt was schneller ist. Dazu habe ich ein kleines Testprogramm geschrieben. Dieses kann mit unterschiedlichen Preprocessor-Optionen kompiliert werden. So habe ich 4 Testprogramme erstellt. Für getxattr und fgetxattr jeweils ein Programm, das ein Attribut liest und eines das 32 Attribute liest.

Bei einem Verzeichnis mit 128.000 Dateien hab ich folgende Werte erhalten:

getxattr:1  getxattr:32  fgetattr:1  fgetattr:32
------------------------------------------------
246100055   654704421    456172044   749849574
230183311   663632162    457183706   769223423
247109480   654775136    440397212   743349119

Die Datei erst zu öffnen um dann fgetxattr zu nutzen ist also langsamer. Erst als ich das Programm so modifiziert habe, dass es mehrere hundert Attribute liest, war es etwas schneller. Das ist jedoch ein eher unrealistisches Szenario. Allerdings war das ganze generell sehr schnell, so dass es eigentlich egal ist, welche Methode man anwendet.

Autor: Olaf | 0 Kommentare | Tags: linux, c, xattr, benchmark

Festplatten-Benchmark mit bonnie++

2016-12-21 21:33:32.0

Ein einfaches Tool für Benchmarks von Festplatten bzw. Dateisystemen ist bonnie++. Man startet es einfach und es werden im aktuellen Arbeitsverzeichnis verschiedene Tests durchgeführt.

Hier mal ein Beispiel, auch wieder auf einem Raspberry Pi:

$ bonnie++
Writing with putc()...done
Writing intelligently...done
Rewriting...done
Reading with getc()...done
Reading intelligently...done
start 'em...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version 1.03e       ------Sequential Output------ --Sequential Input- --Random-
                    -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
Machine        Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
raspi.local      1G  3565  95 20890  44  9180  19  3822  97 24020  27  1060  23
                    ------Sequential Create------ --------Random Create--------
                    -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
              files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                 16  3930  96 +++++ +++  6338 106  3920  94 +++++ +++  5559  96
raspi.local,1G,3565,95,20890,44,9180,19,3822,97,24020,27,1059.6,23,16,3930,96,+++++,+++,6338,106,3920,94,+++++,+++,5559,96

Die Tests mit putc() und getc() sind recht CPU-lastig, da hier Zeichen einzelnd geschrieben oder gelesen werden. Die block-basierten Tests hingegen zeigen gut den IO-Durchsatz.

Was auch auffällt, bei den Create-Tests fehlen die Werte für Read. Dies liegt daran, das in meinem Fall die Tests zu schnell fertig waren und dadurch keine genauen Ergebnisse berechnet werden können. Bonnie++ zeigt daher lieber keinen Wert an.

Autor: Olaf | 0 Kommentare | Tags: benchmark

Netzwerk-Benchmark mit iperf

2016-12-20 22:01:28.0

Mit iperf kann man sehr einfach sein Netzwerk benchmarken. Dazu startet man auf einem Computer einen iperf-Server:

$ iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 85.3 KByte (default)
------------------------------------------------------------

Und auf einem anderen Computer startet man den iperf-Client und gibt den Server an (in diesem Fall rpi):

$ iperf -c rpi
------------------------------------------------------------
Client connecting to rpi, TCP port 5001
TCP window size: 85.0 KByte (default)
------------------------------------------------------------
[  3] local 192.168.178.170 port 39890 connected with 192.168.178.28 port 5001
[ ID] Interval       Transfer     Bandwidth
[  3]  0.0-10.0 sec   114 MBytes  95.5 Mbits/sec

Man sieht, ein Raspberry Pi 1 kann sein 100 Mbit/s LAN gut auslasten. Allerdings hat das bei mir auch zu 75% CPU-Last geführt.

Autor: Olaf | 0 Kommentare | Tags: network, benchmark

stat Benchmark

2016-02-09 20:13:00.0

Der Syscall stat wird benutzt um an Informationen wie Dateigröße oder Änderungsdatum einer Datei zu gelangen. Die Funktion erwartet als Argumente nur einen Dateipfad und einen Buffer. Daneben gibt es noch die Variante fstat, die statt eines Dateipfades einen Filedescriptor erwartet, und fstatat, die den Filedescriptor eines geöffneten Verzeichnisses und einen Pfad relativ zu dem Verzeichnis erwartet.

int stat(const char *restrict path, struct stat *restrict buf);
int fstat(int fildes, struct stat *buf);
int fstatat(int fd, const char *restrict path,
    struct stat *restrict buf, int flag);

Mich hat jetzt ein Performancevergleich zwischen den Funktionen interessiert. Zum einen für den Fall, dass man für jede Datei in einem Verzeichnis stat aufrufen will. Hier würde sich der Einsatz von fstatat anbieten. Der andere Fall wäre, wenn man eine Datei öffnen und stat-en will. Um dies zu testen hab ich ein primitives Programm geschrieben, dass man hier findet. Das Programm erwartet als Argument einen Pfad zu einem Verzeichnis, welches es zunächst ließt. Danach führt es 4 Tests durch und misst für jeden die Zeit:

Ein kleiner Test unter Linux ergab:

test 195 files:

test_stat
time: 496386 ns

test_fstatat
time: 246039 ns

----------------------------------------

test_open_stat
time: 1106593 ns

test_open_fstat
time: 885549 ns

Ähnliche Ergebnisse konnte ich auch unter FreeBSD und Solaris, mit Festplatten und SSDs, reproduzieren. Der Vergleich zwischen test_stat und test_fstatat zeigt, dass fstatat deutlich schneller ist. In beiden Tests wird auch nur pro Datei jeweils ein Syscall aufgerufen. Bei test_open_stat und test_open_fstat wird in beiden Fällen zunächst open benutzt um die Datei zu öffnen und es zeigt sich, dass in diesem Fall fstat auch schneller ist als stat, allerdings fällt der Unterschied hier nicht so sehr ins Gewicht.

Autor: Olaf | 0 Kommentare | Tags: c, unix, linux, benchmark