[gelöst] CPU-Auslastung mit Bordmitteln der Bash begrenzen

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
Tintom
Moderator
Beiträge: 3033
Registriert: 14.04.2006 20:55:15
Wohnort: Göttingen

[gelöst] CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von Tintom » 22.12.2018 13:45:25

Hallo zusammen,

ich habe einen vServer, dessen Ressourcen ich mir mit anderen teile. Die Anzahl der zur Verfügung stehenden CPU-Cores hat mich dazu verleitet rechenintensive Operationen auf den Server auszulagern, was naturgemäß bei den anderen Usern nicht gut ankommt. Ich habe also meine rechenintensiven Prozesse mit einem nice -n19 <Prozess> gestartet, was aber seitens der Administratoren auch unerwünscht war.

Tools wie Debiancpulimit oder cgroup fallen raus, weil mangels su-Rechte nicht installierbar.

Die Funktionsweise von cpulimit ist, sofern ich das richtig verstehe, einen Prozess zu starten und wieder schlafen zu legen. Je länger der Prozess schläft, desto geringer ist die Arbeitslast, die der Prozess erzeugt. Umgesetzt in der Bash könnte das so aussehen:

#!/bin/bash
#
cat /dev/zero > /tmp/outfile.dat &
#
PROC=$!
SLEEP=0
#
while :; do
case "$SLEEP" in
0) kill -19 $PROC && SLEEP=1 && sleep 0.0005 ;;
1) kill -18 $PROC && SLEEP=0 ;;
esac
done


Problem: Das Skript erzeugt bei mir eine Last von etwa 16%, der eigentliche Befehl cat jedoch nur 3%. Gibt es eine Möglichkeit den Overhead durch das Skript zu reduzieren, damit der Prozess, der limitiert werden soll, ein größeres Stück vom Kuchen abkriegt?

//edit:
Wenn ich den o.g. cat-Befehl abändere zu cat /dev/urandom > /dev/null bekomme ich anstelle 3%-Auslastung plötzlich ~40% Auslastung auf der CPU, neben den 16%, die für das eigentliche Skript anfallen. Wie kann das sein?
Zuletzt geändert von Tintom am 23.12.2018 08:11:52, insgesamt 1-mal geändert.

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von Phineas » 22.12.2018 16:34:11

Wenn Du kein sleep hinter dem Sigcont hast, wird der Prozess doch fast sofort wieder gestoppt. Vielleicht testest Du mal mit (unterschiedlich großen) Sleepzeiten für Sigstop und Sigcont, dann sollte die Schleife selbst auch nicht mehr so viel CPU-Last erzeugen.

Dann brauchst Du übrigens auch kein case mehr, einfach Sigstop, Sleep, Sigcont, sleep und wieder von vorn, das sollte die Schleife auch nochmal entlasten.

Benutzeravatar
MSfree
Beiträge: 10727
Registriert: 25.09.2007 19:59:30

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von MSfree » 22.12.2018 16:48:03

sleep erwartet ein Zeitinterval in Sekunden. 0.0005 wird zu Null gerunden, was dann dazu führt, daß du das System mit einer extremen Folge von teurern kill-Aufrufen auslastest.

Eigentlich wäre nice -19 schon der richtige Weg. Ein derart runterpriorisierter Prozeß bekommt zwar 100% der CPU, wenn nichts anderes läuft, muß aber sofort zurückstecken, wenn irgenjemand anderes die CPU braucht. Warum das deine Mitstreiter irgendwie falsch verstanden haben, kann ich dir natürlich nicht sagen.

Problematisch wird es erst, wenn ein Prozeß den Hauptspeicher belagert und das System ins Swappen gerät, wenn andere Prozesse laufen sollen. Da hilft dann auch kein nice oder Basteleien mit sleep.

RobertDebiannutzer
Beiträge: 385
Registriert: 16.06.2017 09:52:36

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von RobertDebiannutzer » 22.12.2018 16:52:49

Es gibt auch noch ein bash-builtin namens "ulimit". Tipp mal

Code: Alles auswählen

help ulimit
(natürlich nur in einer bash-session).

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von Phineas » 22.12.2018 17:16:57

MSfree hat geschrieben: ↑ zum Beitrag ↑
22.12.2018 16:48:03
sleep erwartet ein Zeitinterval in Sekunden.
Bei mir nimmt sleep auch Sekundenbruchteile.

Code: Alles auswählen

time for ((i=1;i<=30;i++)) do sleep .1 ; printf \\r$i ; done
Das Ding läuft artig 3 Sekunden lang (plus etwas runtime), sleept also tatsächlich 0.1 Sekunden.

Benutzeravatar
MSfree
Beiträge: 10727
Registriert: 25.09.2007 19:59:30

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von MSfree » 22.12.2018 18:57:58

Phineas hat geschrieben: ↑ zum Beitrag ↑
22.12.2018 17:16:57
Bei mir nimmt sleep auch Sekundenbruchteile.
Interessant, again what learned.

Trotzdem ist der oben genannte Wert von 0.0005s viel zu klein um irgendetwas, ausser Last durch kill- und sleep-Aufrufe zu bewirken.

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von Phineas » 22.12.2018 19:21:20

MSfree hat geschrieben: ↑ zum Beitrag ↑
22.12.2018 18:57:58
Trotzdem ist der oben genannte Wert von 0.0005s viel zu klein um irgendetwas, ausser Last durch kill- und sleep-Aufrufe zu bewirken.
Das sehe ich auch so, 2000 Schleifendurchläufe pro Sekunde ist hier viel zu viel.

Als leidenschaftlich faule Sau, sehe ich mir nicht "help ulimit" an, unterstütze aber die entsprechende Empfehlung von RobertDebiannutzer.

Benutzeravatar
Tintom
Moderator
Beiträge: 3033
Registriert: 14.04.2006 20:55:15
Wohnort: Göttingen

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von Tintom » 22.12.2018 22:19:39

Danke für eure Antworten!

ulimit kannte ich noch gar nicht, danke!
Allerdings weiß ich nicht so recht, wie ich damit umgehen soll.

$help ulimit

ulimit: ulimit [-SHabcdefiklmnpqrstuvxPT] [Grenze]
Modify shell resource limits.

Provides control over the resources available to the shell and processes
it creates, on systems that allow such control.

Options:
-S use the `soft' resource limit
-H use the `hard' resource limit
-a all current limits are reported
-b the socket buffer size
-c the maximum size of core files created
-d the maximum size of a process's data segment
-e the maximum scheduling priority (`nice')
-f the maximum size of files written by the shell and its children
-i the maximum number of pending signals
-k the maximum number of kqueues allocated for this process
-l the maximum size a process may lock into memory
-m the maximum resident set size
-n the maximum number of open file descriptors
-p the pipe buffer size
-q the maximum number of bytes in POSIX message queues
-r the maximum real-time scheduling priority
-s the maximum stack size
-t the maximum amount of cpu time in seconds
-u the maximum number of user processes
-v the size of virtual memory
-x the maximum number of file locks
-P the maximum number of pseudoterminals
-T the maximum number of threads


Ich habe im ersten Anlauf den Parameter -t genommen, aber zum einen läuft der Prozess mit 100% Leistung und zum anderen wird er nach Erreichen des Limits gekillt. Oder nehme ich einfach nur den falschen Parameter?
MSfree hat geschrieben: ↑ zum Beitrag ↑
22.12.2018 18:57:58
Trotzdem ist der oben genannte Wert von 0.0005s viel zu klein um irgendetwas, ausser Last durch kill- und sleep-Aufrufe zu bewirken.
Stimmt, daran hatte ich noch gar nicht gedacht. Wenn ich mit dem Sleep-Paramter ein bisschen rumspiele und höhere Werte benutze, kommen auch realistische Werte bei der Auslastung heraus. Danke!

Benutzeravatar
MSfree
Beiträge: 10727
Registriert: 25.09.2007 19:59:30

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von MSfree » 22.12.2018 22:52:55

ulimit wird dich nicht weiterbringen. Das ist nicht zum Einschränken des Anteils an der CPU geeignet. Man kann damit nur maximale grenzen setzen und wenn diese überschritten werden, wird der Prozeß gekillt.

Es gibt auch keine Möglichkeit unter Linux, den CPU-Anteil z.B. auf 50% zu beschränken. Das ganze wäre auch kompletter Unsinn. Deinen Mitstreitern solltest du mal folgdendes Zeigen. Starte folgende Prozesse:

Code: Alles auswählen

nice -19 gzip -9 -c /dev/zero > /dev/null &
und Du wirst sehen, daß gzip praktisch 100% der CPU belegt. Starte nun einen zweiten Prozeß:

Code: Alles auswählen

gzip -9 -c /dev/zero > /dev/null &
Und du siehst, wie der genicete Prozeß vom normal laufenden verdrängt wird.

100% CPU-Last ist nicht schädlich und führt auch nicht zu einem schlecht reagierenden System, wenn man "CPU-Fresser" runterpriorisiert. Warum sich deine Mitstreiter da so aufregen, zeugt nur von deren Unwissenheit.

Benutzeravatar
Tintom
Moderator
Beiträge: 3033
Registriert: 14.04.2006 20:55:15
Wohnort: Göttingen

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von Tintom » 22.12.2018 22:57:28

Der Hinweis von Phineas hat es schlussendlich gebracht. Nach ein wenig umschreiben sieht die Lösung nun so aus:

#!/bin/bash

cat /dev/urandom > /dev/null &

PROC=$!
SLEEP=0.7
AWAKE=`bc <<<1-$SLEEP`
echo Limit ist `bc <<<$AWAKE*100` Prozent
while :; do
kill -19 $PROC
sleep $SLEEP
kill -18 $PROC
sleep $AWAKE
done


Wenn ich nun top aufrufe, genehmigt sich cat im Schnitt 30% der CPU, das Skript an sich braucht etwa 0,3%. Das passt für mich als Lösung. Vielen Dank an alle Beteiligten!

@MSfree: Ich sehe das genauso wie du, aber der (kommerzielle) Anbieter des vServers hat da leider eine andere Ansicht zu.

Benutzeravatar
Phineas
Beiträge: 348
Registriert: 20.06.2012 20:26:19

Re: CPU-Auslastung mit Bordmitteln der Bash begrenzen

Beitrag von Phineas » 23.12.2018 01:30:08

Tintom hat geschrieben: ↑ zum Beitrag ↑
22.12.2018 22:57:28
... aber der (kommerzielle) Anbieter des vServers hat da leider eine andere Ansicht zu.
Und eine andere Meßmethode und ich fürchte, das ist ausschlaggebend.
(Will sagen dass MSfree Recht hat, aber das nützt so viel, wie eine Abgasmessung bei Volkswagen)

Antworten