Speicherverbrauch von Prozessen richtig ermitteln
Hallo, Ich bin auf eine Lücke in meinem Verständnis der Linux-Speicherverwaltung gestoßen, und suche jetzt Erleuchtung: top -bn1|sed '4,5!d' Mem: 514396k total, 393128k used, 121268k free, 49124k buffers Swap: 1028120k total, 0k used, 1028120k free, 213168k cached Wenn ich rechne: 393128 "used" minus 39124 "buffers" minus 213168 "cached", dann komme ich auf 130836k durch Programme belegten Speicher. Wenn ich aber die Prozessgrößen (Spalte VIRT in top) aufaddiere, komme ich auf einen wesentlich kleineren Wert: top -bn1|sed '1,7d'|awk '{s+=$7}END{print s}' 66923 Dabei ist noch nicht einmal der Speicher abgezogen, den sich verwandte Prozesse teilen (SHR). Diese Diskrepanz wird übrigens auch größer, wenn ich in Runlevel 5 gehe und dann wieder zu Runlevel 3 zurückkehre. Ich frage mich jetzt also, wofür dieser Speicher verwendet wird und wie ich ihn messen kann. (Mein System: SuSE 8.2, 512MB RAM mit einem 2.4.20 4GB-SMP Kernel auf einem Dual-Athlon) Shared Memory ist es jedenfalls nicht, ipcs liefert: ----- Gemeinsamer Speicher: Segmente ----- Schlüssel shmid Besitzer Rechte Bytes nattch Status 0x00000000 0 root 777 1074832 2 0x00000000 786433 th 777 196608 2 dest 0x00000000 917506 th 777 196608 2 dest ----- Semaphorenfelder ----- Schlüssel SemID Besitzer Rechte nsems ----- Nachrichtenwarteschlangen ----- Schlüssel msqid Besitzer Rechte used-bytes messages Grüße Thomas.
Hallo Thomas, hallo Leute, Am Samstag, 14. Juni 2003 15:23 schrieb Thomas Hofer:
Ich bin auf eine Lücke in meinem Verständnis der Linux-Speicherverwaltung gestoßen, und suche jetzt Erleuchtung:
top -bn1|sed '4,5!d'
Mem: 514396k total, 393128k used, 121268k free, 49124k buffers Swap: 1028120k total, 0k used, 1028120k free, 213168k cached
Wenn ich rechne: 393128 "used" minus 39124 "buffers" minus 213168 "cached", dann komme ich auf 130836k durch Programme belegten Speicher. Wenn ich aber die Prozessgrößen (Spalte VIRT in top) ^^^^ aufaddiere, komme ich auf einen wesentlich kleineren Wert:
top -bn1|sed '1,7d'|awk '{s+=$7}END{print s}' ^^ VIRT ist bei mir Spalte 5. Du willst also $5 aufsummieren ;-)
[...]
Weitere Rechenaktionen und Überprüfungen spar ich mir erstmal ;-) Falls Dein top eine andere Spalteneinteilung hat und $7 wirklich VIRT ist, kannst Du Dich ja nochmal melden. Gruß Christian Boltz -- Das ist mir jetzt ehrlich wirklich richtig peinlich... Ich hätte geschworen, damals vsftp installiert zu haben. Hab' ich gar nicht, sondern proFtp... Ähem... also gut, dann bin ich eben damit sehr zufrieden. [Ratti in suse-linux]
Am Mittwoch, 18. Juni 2003 23:56 schrieb Christian Boltz:
Hallo Thomas, hallo Leute,
Am Samstag, 14. Juni 2003 15:23 schrieb Thomas Hofer:
Ich bin auf eine Lücke in meinem Verständnis der Linux-Speicherverwaltung gestoßen, und suche jetzt Erleuchtung:
top -bn1|sed '4,5!d'
Mem: 514396k total, 393128k used, 121268k free, 49124k buffers Swap: 1028120k total, 0k used, 1028120k free, 213168k cached
Wenn ich rechne: 393128 "used" minus 39124 "buffers" minus 213168 "cached", dann komme ich auf 130836k durch Programme belegten Speicher. Wenn ich aber die Prozessgrößen (Spalte VIRT in top)
^^^^
aufaddiere, komme ich auf einen wesentlich kleineren Wert:
top -bn1|sed '1,7d'|awk '{s+=$7}END{print s}'
^^ VIRT ist bei mir Spalte 5. Du willst also $5 aufsummieren ;-)
[...]
Weitere Rechenaktionen und Überprüfungen spar ich mir erstmal ;-) Falls Dein top eine andere Spalteneinteilung hat und $7 wirklich VIRT ist, kannst Du Dich ja nochmal melden.
OK, besten Dank. Wenn ich das nächste Mal versuche, bis 5 zu zählen, werde ich auf jeden Fall einen Taschenrechner verwenden. Ich ziehe mich nun zurück, um still zu weinen. Grüße, Thomas.
Thomas Hofer schrieb:
[...] Wenn ich rechne: 393128 "used" minus 39124 "buffers" minus 213168 "cached", dann komme ich auf 130836k durch Programme belegten Speicher. Wenn ich aber die Prozessgrößen (Spalte VIRT in top) aufaddiere, komme ich auf einen wesentlich kleineren Wert:
top -bn1|sed '1,7d'|awk '{s+=$7}END{print s}'
66923
Dabei ist noch nicht einmal der Speicher abgezogen, den sich verwandte Prozesse teilen (SHR). Diese Diskrepanz wird übrigens auch größer, wenn ich in Runlevel 5 gehe und dann wieder zu Runlevel 3 zurückkehre.
Mal davon abgesehen, dass wie Christian schon schrieb auch bei mir VIRT in Spalte 5 sitzt: es ist auch moeglich, dass dort Einheiten benutzt werden. Normalerweise ist die Ausgabe in Kilobytes, aber es kann auch 18m da stehen, das steht dann fuer 18 Megabytes. Das scheinst Du bei Deiner Addition nicht zu beruecksichtigen. Ferner bin ich mir nicht sicher, ob Du wirklich VIRT aufaddieren willst. VIRT ist ja RES + SWAP. Ich bin mir nicht sicher, ob das alles so einfach geht, wie Du es Dir hier vorstellst. Du findest z.B. eine Zeile wie 12267 root 15 0 278m 22m 4584 S 0.3 4.4 0:52.38 X beim Aufruf von "top", da waere VIRT 278 Megabytes. Das kann aber nicht sein, denn bei mir ist momentan Mem: 514824k total, 494876k used, 19948k free, 46508k buffers Swap: 1004020k total, 8k used, 1004012k free, 292624k cached d.h. used - cached - buffers = 155744 Kilobytes. Laut Deiner Rechnung waere also bei mir nun schon durch VIRT von X (278 MB) alleine mehr Speicher belegt, als durch Programme (ca. 155 MB) ganz allgemein. Irgendwie haut bei Deiner Rechnung etwas nicht hin. Ich glaube nicht, dass VIRT der wirklich belegte RAM + SWAP Speicherplatz ist... Hmm, falls Du genaueres ueber die Ausgabe bzw. das Problem findest, ich waere auch interessiert. CU, Thomson
Am Donnerstag, 19. Juni 2003 21:38 schrieb Thomas Hertweck:
Thomas Hofer schrieb:
[...] Wenn ich rechne: 393128 "used" minus 39124 "buffers" minus 213168 "cached", dann komme ich auf 130836k durch Programme belegten Speicher. Wenn ich aber die Prozessgrößen (Spalte VIRT in top) aufaddiere, komme ich auf einen wesentlich kleineren Wert:
top -bn1|sed '1,7d'|awk '{s+=$7}END{print s}'
66923
Dabei ist noch nicht einmal der Speicher abgezogen, den sich verwandte Prozesse teilen (SHR). Diese Diskrepanz wird übrigens auch größer, wenn ich in Runlevel 5 gehe und dann wieder zu Runlevel 3 zurückkehre.
Mal davon abgesehen, dass wie Christian schon schrieb auch bei mir VIRT in Spalte 5 sitzt: es ist auch moeglich, dass dort Einheiten benutzt werden. Normalerweise ist die Ausgabe in Kilobytes, aber es kann auch 18m da stehen, das steht dann fuer 18 Megabytes. Das scheinst Du bei Deiner Addition nicht zu beruecksichtigen.
Die Einheit wird erst bei Prozessgrößen >=100MB ausgegeben, und solche Prozesse gab es bei mir nicht.
Ferner bin ich mir nicht sicher, ob Du wirklich VIRT aufaddieren willst. VIRT ist ja RES + SWAP.
Stimmt auch, aber da ich keinen Swap belegt hatte, ist RES==VIRT.
Ich bin mir nicht sicher, ob das alles so einfach geht, wie Du es Dir hier vorstellst. Du findest z.B. eine Zeile wie
12267 root 15 0 278m 22m 4584 S 0.3 4.4 0:52.38 X
beim Aufruf von "top", da waere VIRT 278 Megabytes. Das kann aber nicht sein, denn bei mir ist momentan
Mem: 514824k total, 494876k used, 19948k free, 46508k buffers Swap: 1004020k total, 8k used, 1004012k free, 292624k cached
d.h. used - cached - buffers = 155744 Kilobytes. Laut Deiner Rechnung waere also bei mir nun schon durch VIRT von X (278 MB) alleine mehr Speicher belegt, als durch Programme (ca. 155 MB) ganz allgemein. Irgendwie haut bei Deiner Rechnung etwas nicht hin. Ich glaube nicht, dass VIRT der wirklich belegte RAM + SWAP Speicherplatz ist...
Hmm, falls Du genaueres ueber die Ausgabe bzw. das Problem findest, ich waere auch interessiert.
Ich hab eine Idee: wenn ich ein mmap auf eine Datei mache und tatsächlich darauf zugreife, dann ist dieser Speicher sowohl in "cached" als auch in VIRT drinnen. Anders gesagt: Teile vom Cache können zum virtuellen Speicher von Prozessen gehören. Weiters können Cache-Pages gleichzeitig in mehreren Prozessen gemappt sein. Theorie eines Ahnungslosen: Ich könnte mir vorstellen, daß X ein Device-File in seinen virtuellen Speicher mmap-t, hinter dem kein Hauptspeicher steht, sondern vielleicht der Speicher der Graphikkarte. Grüße, Thomas.
Thomas Hofer schrieb:
Am Donnerstag, 19. Juni 2003 21:38 schrieb Thomas Hertweck:
[...] Mal davon abgesehen, dass wie Christian schon schrieb auch bei mir VIRT in Spalte 5 sitzt: es ist auch moeglich, dass dort Einheiten benutzt werden. Normalerweise ist die Ausgabe in Kilobytes, aber es kann auch 18m da stehen, das steht dann fuer 18 Megabytes. Das scheinst Du bei Deiner Addition nicht zu beruecksichtigen.
Die Einheit wird erst bei Prozessgrößen >=100MB ausgegeben, und solche Prozesse gab es bei mir nicht.
Das stimmt aber hoechstens fuer die VIRT Spalte, denn in RES ist dem nicht so. Da habe ich einige 11m, 13m, 14m, usw. Also, da muss man ein bissl aufpassen.
[...] Theorie eines Ahnungslosen: Ich könnte mir vorstellen, daß X ein Device-File in seinen virtuellen Speicher mmap-t, hinter dem kein Hauptspeicher steht, sondern vielleicht der Speicher der Graphikkarte.
Um ehrlich zu sein, ich zaehle mich auch zu den Ahnungslosen bei diesem Problem :-) Aber vielleicht erhellt uns ja noch jemand. CU, Thomson
On Fri, Jun 20, 2003 at 11:46:55PM +0200, Thomas Hertweck wrote:
Theorie eines Ahnungslosen: Ich könnte mir vorstellen, daß X ein Device-File in seinen virtuellen Speicher mmap-t, hinter dem kein Hauptspeicher steht, sondern vielleicht der Speicher der Graphikkarte.
Um ehrlich zu sein, ich zaehle mich auch zu den Ahnungslosen bei diesem Problem :-) Aber vielleicht erhellt uns ja noch jemand.
Bitte sehr: kris@valiant:~> ps axuwww| grep X root 1800 0.2 2.6 86432 6848 ? SL Jun19 5:18 /usr/X11R6/bin/X vt7 -auth /var/lib/xdm/authdir/authfiles/A:0-bH6HYe kris 2004 0.0 0.0 4472 0 ? SW Jun19 0:00 /bin/sh /usr/X11R6/bin/kde kris 17161 0.0 0.2 3544 568 pts/3 S 07:31 0:00 grep X kris@valiant:~> su - Password: valiant:~ # cd /proc/1800 valiant:/proc/1800 # cat maps 08048000-081c3000 r-xp 00000000 03:43 91110 /usr/X11R6/bin/XFree86 ^ Startadresse ^ Endadresse ^ Schreibgeschützt (kein w), daher shareable ^ Gemapped auf dieses Device ^ und diese Indode ^ mit diesem Offset in der Inode ^ Name der Inode, soweit bekannt 081c3000-081f5000 rw-p 0017b000 03:43 91110 /usr/X11R6/bin/XFree86 ^ Anderer Speicherbereich ^ Writeable ^ Selbe Datei, ^ anderer Offset Das zu dem o.a. Text-Segment gehoerende Datensegment 081f5000-08a0c000 rwxp 00000000 00:00 0 ^ Anderer Speicherbereich ^ Keine Datei als Mapping, also Swapfile als Backing Store nehmen. Das ist das zu der o.a. Datei gehoerende BSS-Segment. valiant:/proc/1800 # size /usr/X11R6/bin/XFree86 text data bss dec hex filename 1549510 202776 74400 1826686 1bdf7e /usr/X11R6/bin/XFree86 Jetzt die Libs: 40000000-40014000 r-xp 00000000 03:43 17036 /lib/ld-2.3.2.so 40014000-40015000 rw-p 00014000 03:43 17036 /lib/ld-2.3.2.so 40015000-4001c000 r-xp 00000000 03:43 115283 /usr/X11R6/lib/modules/fonts/libfreetype.so 4001c000-4001d000 rw-p 00006000 03:43 115283 /usr/X11R6/lib/modules/fonts/libfreetype.so Ein paar kleinere Speicherblöcke einblenden: Speicheradresse hier: vvvvvvvv 4001d000-4001e000 rw-s d4680000 03:43 4645 /dev/mem 4001e000-4001f000 rw-s d4601000 03:43 4645 /dev/mem 4001f000-40020000 rw-s d4681000 03:43 4645 /dev/mem 40020000-40021000 rw-s d40c0000 03:43 4645 /dev/mem 40021000-40022000 rw-s d4001000 03:43 4645 /dev/mem 40022000-40023000 rw-s 05c5d000 03:43 10697 /dev/nvidia0 Mehr Libs: 40027000-40034000 r-xp 00000000 03:43 17092 /lib/libz.so.1.1.4 40034000-40036000 rw-p 0000c000 03:43 17092 /lib/libz.so.1.1.4 40036000-40057000 r-xp 00000000 03:43 15318 /lib/libm.so.6 40057000-40058000 rw-p 00020000 03:43 15318 /lib/libm.so.6 40058000-40059000 rw-p 00000000 00:00 0 40059000-4005b000 r-xp 00000000 03:43 17095 /lib/libdl.so.2 4005b000-4005c000 rw-p 00001000 03:43 17095 /lib/libdl.so.2 4005c000-4018b000 r-xp 00000000 03:43 17103 /lib/libc.so.6 4018b000-4018f000 rw-p 0012f000 03:43 17103 /lib/libc.so.6 4018f000-40192000 rw-p 00000000 00:00 0 40192000-4019d000 r-xp 00000000 03:43 15349 /lib/libnss_compat.so.2 4019d000-4019e000 rw-p 0000a000 03:43 15349 /lib/libnss_compat.so.2 4019e000-401b0000 r-xp 00000000 03:43 15334 /lib/libnsl.so.1 401b0000-401b1000 rw-p 00011000 03:43 15334 /lib/libnsl.so.1 401b1000-401da000 rw-p 00000000 00:00 0 VGA Textmode Speicher (64 KB): vvvvvvvv 401da000-401ea000 rw-s 000a0000 03:43 4645 /dev/mem 401ec000-40239000 r-xp 00000000 03:43 89045 /usr/lib/libfreetype.so.6.3.2 40239000-4023d000 rw-p 0004d000 03:43 89045 /usr/lib/libfreetype.so.6.3.2 4023d000-4023e000 rw-p 00000000 00:00 0 4023e000-402c1000 r-xp 00000000 03:43 115421 /usr/X11R6/lib/modules/extensions/libglx.so.1.0.4363 402c1000-402e3000 rw-p 00082000 03:43 115421 /usr/X11R6/lib/modules/extensions/libglx.so.1.0.4363 402e3000-402e4000 rw-p 00000000 00:00 0 402e4000-4077f000 r-xp 00000000 03:43 89939 /usr/lib/libGLcore.so.1.0.4363 4077f000-4078a000 rw-p 0049a000 03:43 89939 /usr/lib/libGLcore.so.1.0.4363 4078a000-407e1000 rw-p 00000000 00:00 0 Und hier der große Block (0x02000000): v Start v Ende v Memory 407e1000-427e1000 rw-s d6000000 03:43 10697 /dev/nvidia0 427e1000-427f1000 rw-s d0000000 03:43 10697 /dev/nvidia0 427f1000-42801000 rw-s d4800000 03:43 10697 /dev/nvidia0 42801000-42809000 rw-s 05e86000 03:43 10697 /dev/nvidia0 42809000-42910000 rw-s 00000000 00:05 0 /SYSV00000000 (deleted) 42910000-44910000 rw-s d6000000 03:43 10697 /dev/nvidia0 44910000-44a17000 rw-s 00000000 00:05 0 /SYSV00000000 (deleted) 44a17000-44a93000 rw-p 00000000 00:00 0 44ac4000-44ac6000 rw-p 000ad000 00:00 0 44e6e000-44e70000 rw-p 00457000 00:00 0 451e7000-451e9000 rw-p 007d0000 00:00 0 bffef000-c0000000 rwxp ffff0000 00:00 0 ^ Der Stack Kristian
Kristian Koehntopp schrieb:
On Fri, Jun 20, 2003 at 11:46:55PM +0200, Thomas Hertweck wrote:
[...] Um ehrlich zu sein, ich zaehle mich auch zu den Ahnungslosen bei diesem Problem :-) Aber vielleicht erhellt uns ja noch jemand.
Bitte sehr:
kris@valiant:~> ps axuwww| grep X root 1800 0.2 2.6 86432 6848 ? SL Jun19 5:18 /usr/X11R6/bin/X vt7 -auth /var/lib/xdm/authdir/authfiles/A:0-bH6HYe kris 2004 0.0 0.0 4472 0 ? SW Jun19 0:00 /bin/sh /usr/X11R6/bin/kde kris 17161 0.0 0.2 3544 568 pts/3 S 07:31 0:00 grep X kris@valiant:~> su - Password: valiant:~ # cd /proc/1800 valiant:/proc/1800 # cat maps [...]
Wir sind unwuerdig, wir sind unwuerdig...[1] :-) Wenn Du nun noch kurz erlaeutern koenntest, wie das nun mit den Ausgaben von "top" und dort insbesondere den Spalten VIRT, RES, und SHR in Einklang zu bekommen ist, dann waere ich gluecklich. Wie Thomas Hofer gezeigt hat, ist es ja mit aufaddieren der einzelnen Spalten nicht getan, um alles konsistent zu erklaeren. Vielen Dank, Thomson [1] Beruehmte Szene aus "Wayne's World"... :-)
On Sat, Jun 21, 2003 at 10:50:52AM +0200, Thomas Hertweck wrote:
Wenn Du nun noch kurz erlaeutern koenntest, wie das nun mit den Ausgaben von "top" und dort insbesondere den Spalten VIRT, RES, und SHR in Einklang zu bekommen ist, dann waere ich gluecklich.
Du meinst wie nachstehend? Oder was willst Du genau vorgerechnet haben? Kristian $ cat /proc/1/status Name: init State: S (sleeping) Tgid: 1 Pid: 1 PPid: 0 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 32 Groups: VmSize: 448 kB VmLck: 0 kB VmRSS: 76 kB VmData: 24 kB VmStk: 4 kB VmExe: 408 kB VmLib: 0 kB SigPnd: 0000000000000000 SigBlk: 0000000000000000 SigIgn: ffffffffd770d8fc SigCgt: 00000000288b2603 CapInh: 0000000000000000 CapPrm: 00000000ffffffff CapEff: 00000000fffffeff $ ./memuse.pl 1 init 417792 s 08048000-080ae000 r-xp 00000000 03:03 163894 /sbin/init 12288 080ae000-080b1000 rw-p 00066000 03:03 163894 /sbin/init 24576 080b1000-080b7000 rwxp 00000000 00:00 0 4096 bffff000-c0000000 rwxp 00000000 00:00 0 share = 417792 ( 408.00 KB) private = 40960 ( 40.00 KB) total = 458752 ( 448.00 KB) ( 91.07 % shareable) $ cat ./memuse.pl #! /usr/bin/perl -- # Kristian Köhntopp <7elhq3$ocs@valiant.koehntopp.de> die "Usage: $0 PID\n" unless $ARGV[0] > 0; $file = sprintf "/proc/%s/cmdline", $ARGV[0]; open IN, "<$file" or die; ($line = <IN>) =~ s/\0//g; close IN; print "$line\n";; $file = sprintf "/proc/%s/maps", $ARGV[0]; open IN, "<$file" or die; while(<IN>) { ( $mem, $prot, $offset, $dev, $inode) = split; ( $start, $stop ) = split "-", $mem; $size = hex($stop) - hex($start); $total += $size; $able = " "; if ($prot =~ /^r-/ and $inode != 0) { $share += $size; $able = "s"; } printf "%12d %s %s", $size, $able, $_; } close IN; printf "share = %12d (%8.2f KB)\n", $share, $share/1024; printf "private = %12d (%8.2f KB)\n", $total-$share, ($total-$share)/1024; printf "total = %12d (%8.2f KB) (%8.2f %% shareable)\n", $total, $total/1024, $share/$total*100;
Am Samstag, 21. Juni 2003 15:09 schrieb Kristian Koehntopp:
On Sat, Jun 21, 2003 at 10:50:52AM +0200, Thomas Hertweck wrote:
Wenn Du nun noch kurz erlaeutern koenntest, wie das nun mit den Ausgaben von "top" und dort insbesondere den Spalten VIRT, RES, und SHR in Einklang zu bekommen ist, dann waere ich gluecklich.
Du meinst wie nachstehend? Oder was willst Du genau vorgerechnet haben?
Die Erklärung der memory-map war sehr informativ, danke. Nur hast du nichts über die Ausgaben von top erzählt, die uns in erster Linie interessieren. "ps axuwww" liefert nämlich nicht das selbe wie "top -bn1" kris@valiant:~> ps axuwww| grep X root 1800 0.2 2.6 86432 6848 ? SL Jun19 5:18 /usr/X11R6/bin/X vt7 -auth /var/lib/xdm/authdir/authfiles/A:0-bH6HYe Die 86432KB sind der Wert VSZ (=VmSize, die Summe aller memory-mappings). Wir dagegen sind von der Spalte VIRT in top ausgegangen, die einen kleineren Wert hat als VmSize. Meine Interpretation von VIRT, die ich im nächsten Absatz widerlegen werde, ist diese: VIRT ist der Anteil vom virtuellen Speicher, der sich tatsächlich im realen Speicher (RAM plus Swap) befindet. RES ist der Anteil im RAM und VIRT-RES==Swap. SHR ist der Anteil, der potentiell mit anderen Prozessen geteilt werden kann (z.b. eine shared Library). Dies kann ich aber nicht mit folgendem in Einklag bringen: Wie ich gerade probiert habe, kann ich Prozesse erzeugen, deren VIRT größer ist als der gesamte Hauptspeicher+Swap, indem ich ein mmap auf /dev/mem mache und dann auf den Speicher lesend zugreife. Konkret: 512MB RAM, 1GB mmap auf /dev/mem und auf die ersten 500MB lesend zugreifen; das ergibt ein VIRT von über 950MB, ohne daß Swap verwendet wird. Vorsicht: Nachdem ich solche Sachen ein paarmal probiert habe, hat der Kernel (2.4.21) angefangen, zu crashen (Bugs im Memorymanagement-Code). Wahrscheinlich lag es daran, daß ich bei einigen Testläufen auf Speicherbereiche >512MB zugegriffen habe, wodurch der Prozess zu loopen begann. Meine Interpretation scheint für das mmap-en von normalen Files zu stimmen, nicht aber für komische character-devices wie /dev/mem. Jedenfalls kann die Aussage "VIRT = SWAP + RES", wie sie in der top-manpage zu finden ist, nicht stimmen. Grüße, Thomas.
participants (4)
-
Christian Boltz
-
Kristian Koehntopp
-
Thomas Hertweck
-
Thomas Hofer