gettimeofday legt system lahm

Gast #5679694
Lesenswert?

Hallo zusammen,

ich möchte in einem Programm alle paar ms eine Aktion ausführen.
Dazu polle ich in einer Funktion gettimeofday und warte dann bis die 
entsprechende Zeit vergangen ist. Das geht auch alles soweit.
Jedoch funktioniert nach einiger Zeit nichts mehr, da das System 
offensichtlich überlastet ist. Offensichtlich zu viele Aufrufe von 
gettimeofday.
Nun meine Frage, wie kann ich dafür sorgen das ich das System nicht 
überlaste und dennoch in der Lage bin die ms zu zählen?

Das Ganze läuft auf Linux, hier ein Beispiel:
1
#include <iostream>
2
#include <time.h>
3
#include <sys/time.h>
4

5
using namespace std;
6
int32_t get_time(void);
7

8
int32_t ms_counter;
9
struct timeval tv;
10
long long time1, time2;
11

12

13

14
int main()
15
{
16
    ms_counter=0;
17
    int32_t lasttime=0;
18
    gettimeofday(&tv, NULL);
19
    time1 = tv.tv_sec*1000LL+tv.tv_usec/1000;
20
while(1)
21
{
22
    if(get_time()-lasttime>=1000)
23
    {
24
        lasttime=get_time();
25
        cout <<"sekunde vorbei"<<lasttime <<endl;
26
    }
27
}
28

29

30

31
    cout << "Hello world!" << endl;
32
    return 0;
33
}
34

35
int32_t get_time(void)
36
{
37

38
    gettimeofday(&tv, NULL);
39
    time2=tv.tv_sec*1000LL+tv.tv_usec/1000;
40
    long delta= time2-time1;
41
    time1=time2;
42
    ms_counter+=(int32_t)delta;
43

44
    return(ms_counter);
45
}

Vielen Dank und Grüße
Michael
Gast #5679722
Lesenswert?

Michael schrieb:
1
while(1)
2
{
3
    if(get_time()-lasttime>=1000)
4
    {
5
        lasttime=get_time();
6
        cout <<"sekunde vorbei"<<lasttime <<endl;
7
    }
8
}

Bau da mal ein delay ein:
1
#include <unistd.h>
2
...
3

4
while(1)
5
{
6
    if(get_time()-lasttime>=1000)
7
    {
8
        lasttime=get_time();
9
        cout <<"sekunde vorbei"<<lasttime <<endl;
10
    }
11
    else
12
    {
13
        usleep(100000);
14
    }
15
}


Sonst belegt dein Programm einen ganzen CPU Kern mit 100%.

Ich fürchte allerdings, dass dadurch das Problem noch nicht gelöst wird.

> Jedoch funktioniert nach einiger Zeit nichts mehr

Wie lange ist "einige Zeit"? Ich habs's ein paar Minuten laufen lassen - 
klappt.
Gast #5680361
Lesenswert?

Ja, das ist schon klar. Allerdings möchte ich jede Millisekunde etwas 
tun und das da oben war nur ein Beispiel.
Zu lange kann ich auch nicht warten, da andere Programmteile noch etwas 
arbeiten müssen.
Also ist die Lösung hier eher soviel wie möglich und so wenig wie nötig.

Gruß
Michael
#5680423
Lesenswert?

Michael schrieb:
> Ja, das ist schon klar. Allerdings möchte ich jede Millisekunde etwas
> tun und das da oben war nur ein Beispiel.

Dann verwende clock_nanosleep. Dem kannst du auch absolute Zeiten 
vorgeben. Du ermittelst einmal am Anfang die Zeit, dann addierst du in 
jedem Zyklus eine Millisekunde dazu und wartest bis zu dem Zeitpunkt, 
der sich daraus ergibt. Damit ist die Zykluszeit immer genau 1 ms, egal 
wie viel Rechenzeit deine Funktion zwischendrin braucht (solange das 
nicht mehr als 1 ms ist, natürlich).

> Zu lange kann ich auch nicht warten, da andere Programmteile noch etwas
> arbeiten müssen.

Dann musst du die Struktur des Programms überdenken. Entweder du hast 
eine Hauptschleife, in der (blockierend) gewartet wird, bis es irgendwas 
zu tun gibt (egal ob nun durch einen Timer oder ankommende Daten oder 
Eingaben des Benutzer), nur dann aufwacht, seine Aufgaben abarbeitet und 
sich wieder schlafen legt. Oder du machst getrennte Threads, um diese 
Dinge zu entkoppeln.
Aber alle 10 µs aufzuwachen, um zu zählen, ob schon eine ms abgelaufen 
ist, ist schlechtes Design. Abgesehen davon gibt es mindest-Dauern für 
die Zeit, die nanosleep schläft und auch eine begrenzte Auflösung, je 
nach Zielsystem.

> Also ist die Lösung hier eher soviel wie möglich und so wenig wie nötig.

Nein, das ist keine sinnvolle Lösung.


Übrigens: Wenn man ein präzises Timing will, ist zu bedenken, dass 
nanosleep wie jeder Syscall durch Signale unterbrochen werden und damit 
vorzeitig zurückkehren kann. Sofern du also mit Signalen arbeitest, 
musst du das berücksichtigen.
Gast #5680470
Lesenswert?

Bitte bedenkt, dass der Task Scheduler jedes laufende Programm aktiv 
unterbricht und irgendwann wieder fortsetzt. Ich meine, dass das 
Umschalt-Intervall ist standardmäßig weit mehr als eine Millisekunde 
lang ist.

Auffallen wird das, sobald man mehr gleichzeitig aktive Programme als 
CPU Kerne hat.
#5680507
Lesenswert?

Wenn man in einem Linux jede Millisekunde was machen will, dann kommt 
man mit sleep, gettimeofday usw. nicht weit. Der Scheduler vom Kernel 
kann den Prozess zu jedem beliebigen Zeitpunkt für jede beliebe Zeit 
anhalten, z.b. beim Speicherauslagern, anderen Prozessen mit höherer 
Priorität sind aktiv, hohe Peripherielast.... Auch ist der 
Scheduler-Zeitschlitz üblicherweise im Bereich von 10-100ms

Für sowas braucht man einen RT Kernel und dazu gibt es dann passende RT 
Bibliotheken und Funktionen.

Ansonsten: Anständige Timings macht man mittels "poll". Dabei gibt man 
eine absolute Zeit an und übergibt eine leere Liste von 
File-Deskriptoren. Dann weis man auch gleich wieviel Zeit man zu spät 
ist, und der Prozess schläft bis zum definierten Zeitpunkt.

Mit File-Descriptoren kann man dann natürlich auch auf "events" 
reagieren.
#5680534
Lesenswert?

Andreas M. schrieb:
> Wenn man in einem Linux jede Millisekunde was machen will, dann kommt
> man mit sleep, gettimeofday usw. nicht weit. Der Scheduler vom Kernel
> kann den Prozess zu jedem beliebigen Zeitpunkt für jede beliebe Zeit
> anhalten, z.b. beim Speicherauslagern, anderen Prozessen mit höherer
> Priorität sind aktiv, hohe Peripherielast.... Auch ist der
> Scheduler-Zeitschlitz üblicherweise im Bereich von 10-100ms
>
> Für sowas braucht man einen RT Kernel und dazu gibt es dann passende RT
> Bibliotheken und Funktionen.

Die oben von mir erwähnte Funktion clock_nanosleep gehört da übrigens 
dazu. Sie gehört zur librt (real time) und lässt ein sehr genaues 
Einhalten der Millisekunde zu, sofern man den Thread auf 
Realtime-Priorität stellt und den Prozess gegen Auslagerung sperrt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren