5 Leistungsbewertung

Um die Leistungsfähigkeit der ersten Version unserer Linux-Implementation auf dem Mikrokern L4 bewerten zu können, führten wir ein frei verfügbares Benchmark-Programm aus. Für eine genauere Analyse der Leistung der Linux-Portierung und eine Optimierung anhand der hier beschriebenen Resultate fanden wir jedoch bisher wenig Zeit.

5.1 Testumgebung

Wir verwendeten für unsere Tests einen Rechner mit einem Pentium-Prozessor (100 MHz), 32 MB Hauptspeicher, NE2000-Netzwerkkarte, BusLogic-SCSI-Controller und einer SCSI-Festplatte. Das Heimatverzeichnis war jeweils über NFS eingebunden.

Als Benchmarkprogramme benutzen wir das frei verfügbare Benchmark-Paket Lmbench [24].

Wir führten die Benchmarks auf der selben Maschine jeweils mehrmals unter Linux/i386 und Linux/L4 aus und verglichen dann die Resultate.

5.2 Meßergebnisse

Lmbench ist ein Benchmark-Paket, das von Larry McVoy entwickelt wurde. Es enthält im wesentlichen ,,Microbenchmarks'', die einzelne Subsysteme des Betriebssystems testen und messen. [24]

Wir führten jeweils drei Messungen mit Linux/i386 bzw. Linux/L4 aus. Auf den folgenden beiden Seiten sind die mit bei diesen Durchläufen erzielten Meßzeiten zu finden: die nächste Seite enthält die absoluten Meßzeiten, die darauffolgende Seite setzt die gemessenen Zeiten miteinander ins Verhältnis.

Die ersten drei Zeilen jeder Tabelle zeigen unter Linux/i386 erzielten Zeiten, die letzten drei die unter Linux/L4 erzielten.

                    L M B E N C H  1 . 0   S U M M A R Y
                    ------------------------------------

            Processor, Processes - times in microseconds
            --------------------------------------------
Host                 OS  Mhz    Null    Null  Simple /bin/sh Mmap 2-proc 8-proc
                             Syscall Process Process Process  lat  ctxsw  ctxsw
--------- ------------- ---- ------- ------- ------- ------- ---- ------ ------
carola      Linux 2.0.0  100       3      2K     12K     73K  239     11     18
carola.1    Linux 2.0.0  100       3      2K     12K     73K  231     11     18
carola.2    Linux 2.0.0  100       3      2K     12K     72K  229     10     19
carola.3   Linux 1.3.94  105      56     16K     39K    143K  518    111    137
carola.4   Linux 1.3.94  105      48     15K     37K    131K  516     92    107
carola.5   Linux 1.3.94  100      51     14K     37K    129K  510     96    106

            *Local* Communication latencies in microseconds
            -----------------------------------------------
Host                 OS  Pipe       UDP    RPC/     TCP    RPC/
                                            UDP             TCP
--------- ------------- ------- ------- ------- ------- -------
carola      Linux 2.0.0      49     213     499     300     669
carola.1    Linux 2.0.0      48     216     489     322     716
carola.2    Linux 2.0.0      45     213     512     315     690
carola.3   Linux 1.3.94     442     891    1480    1104    1926
carola.4   Linux 1.3.94     375     792    1341     979    1735
carola.5   Linux 1.3.94     388     775    1309     962    1734

            *Local* Communication bandwidths in megabytes/second
            ----------------------------------------------------
Host                 OS Pipe  TCP  File   Mmap  Bcopy  Bcopy  Mem   Mem
                                  reread reread (libc) (hand) read write
--------- ------------- ---- ---- ------ ------ ------ ------ ---- -----
carola      Linux 2.0.0   22    9     22     51     23     22   62    35
carola.1    Linux 2.0.0   22   10     22     50     23     22   62    35
carola.2    Linux 2.0.0   22   10     22     51     23     22   62    35
carola.3   Linux 1.3.94    9    8     21     21     20     21   60    35
carola.4   Linux 1.3.94   10    8     17     23     22     21   61    35
carola.5   Linux 1.3.94   10    7     17     25     22     21   61    35

            Memory latencies in nanoseconds
            (WARNING - may not be correct, check graphs)
            --------------------------------------------
Host                 OS   Mhz  L1 $   L2 $    Main mem    Guesses
--------- -------------   ---  ----   ----    --------    -------
carola      Linux 2.0.0    99    10    190         316
carola.1    Linux 2.0.0    99    10    196         316
carola.2    Linux 2.0.0    99    10    223         316
carola.3   Linux 1.3.94   104     -      -           -    Bad mhz?
carola.4   Linux 1.3.94   104     -      -           -    Bad mhz?
carola.5   Linux 1.3.94    99     0    188         312

                L M B E N C H  1 . 0   S U M M A R Y
                ------------------------------------

                  Comparison to best of the breed
                  -------------------------------
                (Best numbers are starred, i.e., *123)

        Processor, Processes - factor slower than the best
        --------------------------------------------------
Host                 OS  Mhz    Null    Null  Simple /bin/sh Mmap 2-proc 8-proc
                             Syscall Process Process Process  lat  ctxsw  ctxsw
--------- ------------- ---- ------- ------- ------- ------- ---- ------ ------
carola      Linux 2.0.0  100      *3     1.0     1.0     1.0  1.0    1.1    *18
carola.1    Linux 2.0.0  100      *3   *1.8K  *12.0K     1.0  1.0    1.1    *18
carola.2    Linux 2.0.0  100      *3     1.0     1.0  *70.6K *229    *10    1.1
carola.3   Linux 1.3.94  105      19     8.7     3.2     2.0  2.3     11    7.6
carola.4   Linux 1.3.94  105      16     7.7     3.0     1.8  2.3    9.2    5.9
carola.5   Linux 1.3.94  100      17     7.4     3.0     1.8  2.2    9.6    5.9

        *Local* Communication latencies - factor slower than the best
        -------------------------------------------------------------
Host                 OS  Pipe       UDP    RPC/     TCP    RPC/
                                            UDP             TCP
--------- ------------- ------- ------- ------- ------- -------
carola      Linux 2.0.0     1.1    *213     1.0    *300    *669
carola.1    Linux 2.0.0     1.1     1.0    *489     1.1     1.1
carola.2    Linux 2.0.0     *45    *213     1.0     1.1     1.0
carola.3   Linux 1.3.94     9.8     4.2     3.0     3.7     2.9
carola.4   Linux 1.3.94     8.3     3.7     2.7     3.3     2.6
carola.5   Linux 1.3.94     8.6     3.6     2.7     3.2     2.6

        *Local* Communication bandwidths - percentage of the best
        ---------------------------------------------------------
Host                 OS Pipe  TCP  File   Mmap  Bcopy  Bcopy  Mem   Mem
                                  reread reread (libc) (hand) read write
--------- ------------- ---- ---- ------ ------ ------ ------ ---- -----
carola      Linux 2.0.0  *22  96%    98%    99%    99%    99%  99%   99%
carola.1    Linux 2.0.0  99%   *9    99%    98%    99%    *21  *61   *35
carola.2    Linux 2.0.0  98%  99%    *22    *51    *22    99%  99%   99%
carola.3   Linux 1.3.94  38%  77%    92%    41%    86%    97%  97%   98%
carola.4   Linux 1.3.94  44%  79%    77%    44%    98%    97%  98%   97%
carola.5   Linux 1.3.94  44%  75%    77%    48%    98%    98%  97%   98%

            Memory latencies in nanoseconds - factor slower than the best
                    (WARNING - may not be correct, check graphs)
            -------------------------------------------------------------
Host                 OS   Mhz  L1 $   L2 $    Main mem    Guesses
--------- -------------   ---  ----   ----    --------    -------
carola      Linux 2.0.0    99  -5.0    1.0         1.0
carola.1    Linux 2.0.0    99  -5.0    1.0         1.0
carola.2    Linux 2.0.0    99  -5.0    1.2         1.0
carola.3   Linux 1.3.94   104     -      -           -    Bad mhz?
carola.4   Linux 1.3.94   104     -      -           -    Bad mhz?
carola.5   Linux 1.3.94    99   ???   *188         1.0

5.3 Interpretation der Meßergebnisse

Auf den ersten Blick fällt auf, daß unter der Linux-Emulation auf L4 gegenüber Linux/i386 die Durchsätze auf 44-99% sinken und die Latenzzeiten auf das 1,8-19-fache steigen. In Absolutwerten heißt das etwa, daß Systemrufe ca. 50 s länger dauern oder daß Pipes nur 10 MB/s Durchsatz erreichen statt 22 MB/s (um die beiden extremsten Beispiele herauszugreifen).

Diese Ergebnisse mögen etwas entmutigend erscheinen; wir glauben jedoch, daß diese Werte für eine erste, unoptimierte Version durchaus innerhalb der zu erwartenden Grenzen liegen. Es soll auch nicht übersehen werden, daß wichtige Meßergebnisse wie TCP- und Dateisystem-Durchsatz im brauchbaren Bereich liegen, was den subjektiven Eindruck bestätigt, daß Linux/L4 im praktischen Betrieb nicht spürbar langsamer ist als Linux/i386.

Im folgenden gehen wir auf einzelne Meßergebnisse ein und stellen Vermutungen an, wie sie zustande kamen. Leider hatten wir aus Zeitgründen noch keine Möglichkeit, diese Hypothesen zu überprüfen; dies muß jedoch im Anschluß an diese Arbeit geschehen.

Systemruf-Latenz:
i386: 3 s - unter L4: >17 s.

Neben den stets auftretenden Extra-Kosten für das Abfangen der Ausnahme auf Nutzerseite sind überflüssige L4-Systemaufrufe eine mögliche Senke für die zusätzlich benötigte Zeit. Jean Wolter fand heraus, daß bei jedem Systemruf bestenfalls mindestens 8 Systemrufe l4_myself() stattfinden (Erfragen der Thread-ID des ausführenden Threads) [25]. Setzt man die Dauer für einen L4-Systemruf bei etwa 1,5 s an [22], so tragen allein diese 8 Systemrufe für 12 s der Systemaufrufzeit bei.

Die l4_myself()-Systemrufe lassen sich leicht einsparen - man kann die Thread-IDs der Threads auf ihrem privaten Stack ablegen und eine Inline-Funktion schreiben, die mit Hilfe des aktuellen Stack-Pointers die Thread-ID ermittelt.

mmap()-Latenz:
i386: ca. 230 s - unter L4: ca. 515 s

Ein Problem beim Einblenden von Speicher in eine Applikation ist, daß momentan für jede mmap()-Operation die Kern-Task zweimal betreten werden muß: Einmal für den eigentlichen Systemruf, der die Seitentabellen entsprechend manipuliert, und ein zweites Mal, wenn der erste Seitenfehler in der manipulierten Region eintritt. Die Ursache ist, daß die Manipulation der Seitentabellen unter L4 nicht automatisch die Seiten in die Nutzer-Task einblendet.

Dies würde auch teilweise das schlechtere Abschneiden beim ,,Mmap reread''-Benchmark (Einblenden bereits im Haupspeicher zwischengespeicherter Seiten) und bei der Prozeßerzeugung erklären.

Eine mögliche Abhilfe wäre hier, bei Systemrufen, die Seiten in den Speicher einblenden, beim Senden der Systemruf-Antwort stets die eingeblendeten Seiten als Flexpages mitzusenden.

1st- und 2nd-Level-Cache-Zugriffszeiten
Offenbar war es diesem Meßprogramm unter L4 nicht möglich, sinnvolle Meßwerte zu ermitteln. Eine mögliche Ursache ist, daß die zur Zeitabfrage benutzte L4-Systemuhr keine s-Auflösung besitzt, sondern nur alle 1 ms aufgefrischt wird. Abhilfe wäre hier die Benutzung des Time-Stamp-Counters der Pentium-CPU, die die aufgetretenen Taktimpulse seit dem Systemstart mitzählt, zur Zeitabfrage.

Michael Hohmuth
29. August 1996