Select Page

Alt, aber bewährt

by | Apr 20, 2017 | Linux, C++

Immer wieder geht es in der IT um Vergleiche,  z.B. bei der Web-Entwicklung (NodeJS vs. PHP), der Datenhaltung (MongoDB vs. SQL-Datenbanken) oder auch scheinbaren Kleinigkeiten wie das Einlesen einer Datei in den Arbeitsspeicher.
Letztgenannter Vorgang würde bspw. in der Programmiersprache C unter Linux und anderen POSIX-Systemen wie folgt aussehen (Prüfungen auf Fehler habe ich der Übersichtlichkeit halber weggelassen):

void* read_file(char const *path, size_t *length) {
    int fd;
    struct stat stats;
    void *buf, *pos;
    ssize_t current_read;
    size_t remain;
    
    fd = open(path, O_RDONLY);
    fstat(fd, &stats);
    buf = malloc(stats.st_size);
    pos = buf;
    remain = stats.st_size;
    for (;;) {
        current_read = read(fd, pos, remain);        
        if (current_read == 0) {
            break;
        }
        *(char**)&pos += current_read;
        remain -= (size_t)current_read;
    }
    
    close(fd);
    *length = stats.st_size;
    return buf;
}

Die Alternative dazu wäre die Verwendung von mmap():

void* read_file_via_mmap(char const *path, size_t *length) {
    int fd;
    struct stat stats;
    void *addr, *buf;
    
    fd = open(path, O_RDONLY);
    fstat(fd, &stats);
    addr = mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
    buf = malloc(stats.st_size);
    memcpy(buf, addr, stats.st_size);
    munmap(addr, stats.st_size);
    close(fd);
    *length = stats.st_size;
    return buf;
}

Deren Verfechter werben damit, dass die Anzahl der Systemaufrufe pro Datei konstant ist. Dem kann ich nicht widersprechen – die Datei wird mit open() geöffnet und mit mmap() in den Adressbereich integriert. Damit kann auf den Inhalt zugegriffen werden als befände er sich im Arbeitsspeicher. Das ermöglicht das anschließende Kopieren mit Hilfe von memcpy().
Aber das hilft einem nur weiter, wenn das auch tatsächlich messbar Zeit spart – dies ist definitiv nicht der Fall:

aklimov@ws-aklimov:~$ time ./read garbage
real    0m8.108s
user    0m0.000s
sys     0m3.664s
aklimov@ws-aklimov:~$ time ./mmap garbage
real    0m8.099s
user    0m0.652s
sys     0m3.000s
aklimov@ws-aklimov:~$

Das Lesen einer Datei (3 GB) hat im konkreten Fall nicht viel weniger Zeit in Anspruch genommen. Die Verwendung von mmap() hat lediglich ca. 660 Millisekunden von der linken in die rechte Tasche transferiert. Um genau zu sein – die Systemaufrufe der konventionellen Methode (strace):

open("garbage", O_RDONLY)               = 3                                                                                                                                                  
read(3, "\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0"..., 3221225472) = 2147479552                                                      
read(3, "\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0\377\0"..., 1073745920) = 1073745920                                                      
read(3, "", 0)                          = 0
close(3)                                = 0

… vs. mmap():

open("garbage", O_RDONLY)               = 3
mmap(NULL, 3221225472, PROT_READ, MAP_SHARED, 3, 0) = 0x7ff5423c6000
munmap(0x7ff5423c6000, 3221225472)      = 0
close(3)                                = 0

Zwar benötigt die konventionelle Methode im konkreten Fall einen Systemaufruf mehr, aber angesichts der Dateigröße ist das meiner Meinung nach trotzdem vergleichsweise effizient.

Fazit

Nicht alles was glänzt ist auch Gold. Und mit Kaffeesatzlesen ist niemandem geholfen.

Alexander Klimov
Alexander Klimov
Senior Developer

Alexander hat 2017 seine Ausbildung zum Developer bei NETWAYS erfolgreich abgeschlossen. Als leidenschaftlicher Programmierer und begeisterter Anhänger der Idee freier Software, hat er sich dabei innerhalb kürzester Zeit in die Herzen seiner Kollegen im Development geschlichen. Wäre nicht ausgerechnet Gandhi sein Vorbild, würde er von dort aus daran arbeiten, seinen geheimen Plan, erst die Abteilung und dann die Weltherrschaft an sich zu reißen, zu realisieren - tut er aber nicht. Stattdessen beschreitet er mit der Arbeit an Icinga Web 2 bei uns friedliche Wege.

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

More posts on the topic Linux | C++

Kickstart your Laptop with Linux

Alle paar Jahre bekomme ich einen neuen Laptop bei Netways. Vor zwei Wochen war es wieder so weit und somit eine gute Gelegenheit mal wieder die Betriebssystem-Frage zu stellen. Die alte Frage also: "Welches Linux ist das Beste?". Also für mich ganz persönlich. Nicht...

Ansible – Testing roles with Molecule

Ansible is a widely used and a powerful open-source configuration and deployment management tool. It can be used for simple repetitive daily tasks or complex application deployments, therefore Ansible is able to cover mostly any situation. If used in complex or...

NETWAYS Support Collector Roadmap

Den Support Collector konnte ich bereits in meinem letzten Blogpost vorstellen. Für alle die den Beitrag verpasst haben, hier kurz umrissen was es ist: Bei dem Tool handelt es sich um einen von uns geschriebenen Datensammler, welche alle möglichen Support relevanten...