Wie messe ich die Zeit in Millisekunden mit ANSI C?

127

Gibt es eine Möglichkeit, die Zeit nur mit ANSI C mit einer Genauigkeit von Millisekunden oder mehr zu messen? Ich habe time.h durchsucht, aber nur Funktionen mit zweiter Genauigkeit gefunden.

corto
quelle
4
Beachten Sie den Unterschied zwischen Präzision und Genauigkeit. Sie können eine Zeit mit Millisekunden erhalten Präzision durch die Zeit in Sekunden zu nehmen und mit 1000 multipliziert wird , aber das ist nichts. ms-Präzisionsfunktionen haben nicht unbedingt eine ms-Genauigkeit - obwohl sie im Allgemeinen eine bessere Genauigkeit als 1s aufweisen.
Steve Jessop
2
Die einfache Antwort lautet NEIN. ANSI C unterstützt keine Millisekundengenauigkeit oder besser. Die komplexere Antwort hängt davon ab, was Sie versuchen - ehrlich gesagt ist der gesamte Bereich ein Albtraum -, selbst wenn Sie die Verwendung der weit verbreiteten Posix-Funktionen zulassen. Sie verwenden den Begriff "Maß", daher gehe ich davon aus, dass Sie eher an einem Intervall als an der "Wanduhr" interessiert sind. Aber versuchen Sie, einen absoluten Zeitraum oder eine CPU-Auslastung durch Ihren Prozess zu messen?
Ölmessstab
2
Ich wollte nur sagen, SOF hat gerade wieder meinen Speck gerettet
;-)

Antworten:

92

Es gibt keine ANSI C-Funktion, die eine bessere Auflösung als 1 Sekunde gettimeofdaybietet, aber die POSIX-Funktion bietet eine Mikrosekundenauflösung. Die Uhrfunktion misst nur die Zeit, die ein Prozess für die Ausführung aufgewendet hat, und ist auf vielen Systemen nicht genau.

Sie können diese Funktion folgendermaßen verwenden:

struct timeval tval_before, tval_after, tval_result;

gettimeofday(&tval_before, NULL);

// Some code you want to time, for example:
sleep(1);

gettimeofday(&tval_after, NULL);

timersub(&tval_after, &tval_before, &tval_result);

printf("Time elapsed: %ld.%06ld\n", (long int)tval_result.tv_sec, (long int)tval_result.tv_usec);

Dies kehrt Time elapsed: 1.000870auf meinem Computer zurück.

Robert Gamble
quelle
30
Leichte Einschränkung: gettimeofday () ist nicht monoton, was bedeutet, dass es herumspringen (und sogar rückwärts gehen) kann, wenn Ihr Computer beispielsweise versucht, die Synchronisation mit einem Netzwerkzeitserver oder einer anderen Zeitquelle aufrechtzuerhalten.
Ölmessstab
3
Um genau zu sein: In ISO C99 (das meiner Meinung nach in diesem Teil mit ANSI C kompatibel ist) gibt es nicht einmal eine Garantie für eine zeitliche Auflösung. (ISO C99, 7.23.1p4)
Roland Illig
6
Es ist erwähnenswert, dass timeval::tv_useces immer unter einer Sekunde ist, es ist eine Schleife. Dh um Zeitunterschiede von mehr als 1 Sekunde zu nehmen, sollten Sie:long usec_diff = (e.tv_sec - s.tv_sec)*1000000 + (e.tv_usec - s.tv_usec);
Alexander Malakhov
4
@ Dipstick: Beachten Sie jedoch, dass z. B. NTP Ihre Uhr niemals rückwärts bewegt, bis Sie dies ausdrücklich anweisen.
thejh
1
Die Zeitsubtraktionslogik von @AlexanderMalakhov ist in der timersubFunktion enthalten. Wir können die tval_resultWerte (tv_sec und tv_usec) unverändert verwenden.
x4444
48
#include <time.h>
clock_t uptime = clock() / (CLOCKS_PER_SEC / 1000);
Nick Van Brunt
quelle
CLOCKS_PER_SEC ist auf vielen Systemen auf 1000000 eingestellt. Drucken Sie den Wert aus, um sicherzugehen, bevor Sie ihn auf diese Weise verwenden.
Ysap
16
Da es sich um Uhren pro Sekunde handelt, spielt es keine Rolle, um welchen Wert es sich handelt. Der resultierende Wert von clock () / CLOCKS_PER_SEC wird in Sekunden angegeben (zumindest sollte dies der Fall sein). Durch Teilen durch 1000 wird dies in Millisekunden umgewandelt.
David Young
14
Laut C-Referenzhandbuch können clock_t-Werte ab etwa 36 Minuten umlaufen. Wenn Sie eine lange Berechnung messen, müssen Sie sich dessen bewusst sein.
CyberSkull
4
Beachten Sie auch, dass die Ganzzahldivision CLOCKS_PER_SEC / 1000möglicherweise ungenau ist, was sich auf das Endergebnis auswirken kann (obwohl es meiner Erfahrung CLOCKS_PER_SECnach immer ein Vielfaches von 1000 war). Das Tun (1000 * clock()) / CLOCKS_PER_SECist weniger anfällig für Ungenauigkeiten bei der Teilung, andererseits ist es anfälliger für Überläufe. Nur einige Punkte zu beachten.
Cornstalks
4
Misst dies nicht die CPU-Zeit und nicht die Wandzeit?
krs013
27

Ich benutze immer die Funktion clock_gettime () und gebe die Zeit von der Uhr CLOCK_MONOTONIC zurück. Die zurückgegebene Zeit ist die Zeit in Sekunden und Nanosekunden seit einem nicht näher bezeichneten Zeitpunkt in der Vergangenheit, z. B. dem Systemstart der Epoche.

#include <stdio.h>
#include <stdint.h>
#include <time.h>

int64_t timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
  return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
           ((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}

int main(int argc, char **argv)
{
  struct timespec start, end;
  clock_gettime(CLOCK_MONOTONIC, &start);

  // Some code I am interested in measuring 

  clock_gettime(CLOCK_MONOTONIC, &end);

  uint64_t timeElapsed = timespecDiff(&end, &start);
}

quelle
5
clock_gettime () ist nicht ANSI C.
PowerApp101
1
Außerdem ist CLOCK_MONOTONIC auf vielen Systemen (einschließlich vieler Linux-Plattformen) nicht implementiert.
Ölmessstab
2
@ PowerApp101 Es gibt keine gute / robuste ANSI C-Methode, um dies zu tun. Viele der anderen Antworten basieren eher auf POSIX als auf ANCI C. Davon abgesehen glaube ich das heute. @ Dipstick Heute glaube ich, dass die meisten modernen Plattformen [Zitieren erforderlich] unterstützen clock_gettime(CLOCK_MONOTONIC, ...)und es sogar das Feature-Test-Makro gibt _POSIX_MONOTONIC_CLOCK.
Omninonsense
22

Implementierung einer tragbaren Lösung

Da hier bereits erwähnt wurde, dass es keine richtige ANSI-Lösung mit ausreichender Genauigkeit für das Zeitmessproblem gibt, möchte ich darüber schreiben, wie man eine tragbare und wenn möglich hochauflösende Zeitmesslösung erhält.

Monotone Uhr gegen Zeitstempel

Generell gibt es zwei Möglichkeiten der Zeitmessung:

  • monotone Uhr;
  • aktueller (Datums-) Zeitstempel.

Der erste verwendet einen monotonen Taktzähler (manchmal wird er als Tick-Zähler bezeichnet), der Ticks mit einer vordefinierten Frequenz zählt. Wenn Sie also einen Tick-Wert haben und die Frequenz bekannt ist, können Sie Ticks einfach in verstrichene Zeit umwandeln. Es ist tatsächlich nicht garantiert, dass eine monotone Uhr die aktuelle Systemzeit in irgendeiner Weise widerspiegelt. Sie kann auch Ticks seit einem Systemstart zählen. Es garantiert jedoch, dass eine Uhr unabhängig vom Systemstatus immer stärker hochgefahren wird. Normalerweise ist die Frequenz an eine hochauflösende Hardwarequelle gebunden, weshalb sie eine hohe Genauigkeit bietet (abhängig von der Hardware, aber der Großteil der modernen Hardware hat keine Probleme mit hochauflösenden Taktquellen).

Der zweite Weg liefert einen (Datums-) Zeitwert basierend auf dem aktuellen Systemuhrwert. Es kann auch eine hohe Auflösung haben, hat jedoch einen großen Nachteil: Diese Art von Zeitwert kann durch verschiedene Systemzeitanpassungen beeinflusst werden, z. B. Zeitzonenänderung, Änderung der Sommerzeit (DST), Aktualisierung des NTP-Servers, System-Ruhezustand usw. auf. Unter bestimmten Umständen können Sie einen negativen Wert für die verstrichene Zeit erhalten, der zu einem undefinierten Verhalten führen kann. Tatsächlich ist diese Art von Zeitquelle weniger zuverlässig als die erste.

Die erste Regel bei der Zeitintervallmessung ist daher, wenn möglich eine monotone Uhr zu verwenden. Es hat normalerweise eine hohe Präzision und ist vom Design her zuverlässig.

Fallback-Strategie

Bei der Implementierung einer tragbaren Lösung sollte eine Fallback-Strategie in Betracht gezogen werden: Verwenden Sie eine monotone Uhr, falls verfügbar, und greifen Sie auf Zeitstempel zurück, wenn das System keine monotone Uhr enthält.

Windows

Es gibt einen großartigen Artikel mit dem Titel " Erfassen hochauflösender Zeitstempel auf MSDN zur Zeitmessung unter Windows", in dem alle Details beschrieben werden, die Sie möglicherweise zur Software- und Hardwareunterstützung benötigen. Um einen hochpräzisen Zeitstempel unter Windows zu erhalten, sollten Sie:

  • Abfragen einer Timer-Frequenz (Ticks pro Sekunde) mit QueryPerformanceFrequency :

    LARGE_INTEGER tcounter;
    LARGE_INTEGER freq;    
    
    if (QueryPerformanceFrequency (&tcounter) != 0)
        freq = tcounter.QuadPart;

    Die Timer-Frequenz ist beim Systemstart festgelegt, sodass Sie sie nur einmal abrufen müssen.

  • Fragen Sie den aktuellen Ticks-Wert mit QueryPerformanceCounter ab :

    LARGE_INTEGER tcounter;
    LARGE_INTEGER tick_value;
    
    if (QueryPerformanceCounter (&tcounter) != 0)
        tick_value = tcounter.QuadPart;
  • Skalieren Sie die Ticks auf die verstrichene Zeit, dh auf Mikrosekunden:

    LARGE_INTEGER usecs = (tick_value - prev_tick_value) / (freq / 1000000);

Laut Microsoft sollten Sie unter Windows XP und späteren Versionen in den meisten Fällen keine Probleme mit diesem Ansatz haben. Sie können aber auch zwei Fallback-Lösungen unter Windows verwenden:

  • GetTickCount gibt die Anzahl der Millisekunden an, die seit dem Start des Systems vergangen sind. Es wird alle 49,7 Tage verpackt. Messen Sie daher vorsichtig längere Intervalle.
  • GetTickCount64 ist eine 64-Bit-Version von GetTickCount, ist jedoch ab Windows Vista und höher verfügbar.

OS X (macOS)

OS X (macOS) verfügt über eigene Mach-Absolutzeiteinheiten, die eine monotone Uhr darstellen. Der beste Einstieg ist der Apple-Artikel Technische Fragen und Antworten QA1398: Mach Absolute Time Units, in dem (anhand der Codebeispiele) beschrieben wird, wie mithilfe der Mach-spezifischen API monotone Ticks abgerufen werden. Es gibt auch eine lokale Frage mit dem Namen clock_gettime-Alternative in Mac OS X, die Sie am Ende möglicherweise etwas verwirrt darüber macht, was Sie mit dem möglichen Wertüberlauf tun sollen, da die Zählerfrequenz in Form von Zähler und Nenner verwendet wird. Ein kurzes Beispiel, wie man die verstrichene Zeit erhält:

  • Holen Sie sich den Taktfrequenzzähler und Nenner:

    #include <mach/mach_time.h>
    #include <stdint.h>
    
    static uint64_t freq_num   = 0;
    static uint64_t freq_denom = 0;
    
    void init_clock_frequency ()
    {
        mach_timebase_info_data_t tb;
    
        if (mach_timebase_info (&tb) == KERN_SUCCESS && tb.denom != 0) {
            freq_num   = (uint64_t) tb.numer;
            freq_denom = (uint64_t) tb.denom;
        }
    }

    Sie müssen das nur einmal tun.

  • Fragen Sie den aktuellen Tick-Wert ab mit mach_absolute_time:

    uint64_t tick_value = mach_absolute_time ();
  • Skalieren Sie die Ticks mit dem zuvor abgefragten Zähler und Nenner auf die verstrichene Zeit, dh auf Mikrosekunden:

    uint64_t value_diff = tick_value - prev_tick_value;
    
    /* To prevent overflow */
    value_diff /= 1000;
    
    value_diff *= freq_num;
    value_diff /= freq_denom;

    Die Hauptidee, um einen Überlauf zu verhindern, besteht darin, die Ticks auf die gewünschte Genauigkeit zu verkleinern, bevor Zähler und Nenner verwendet werden. Da die anfängliche Timer-Auflösung in Nanosekunden angegeben ist, teilen wir sie durch 1000Mikrosekunden. Sie finden den gleichen Ansatz wie in time_mac.c von Chromium . Wenn Sie wirklich eine Genauigkeit von Nanosekunden benötigen, lesen Sie bitte Wie kann ich mach_absolute_time verwenden, ohne überzulaufen? .

Linux und UNIX

Der clock_gettimeAnruf ist der beste Weg auf jedem POSIX-freundlichen System. Es kann die Zeit von verschiedenen Uhrquellen abfragen, und die, die wir brauchen, ist CLOCK_MONOTONIC. Nicht alle Systeme, die clock_gettimeUnterstützung CLOCK_MONOTONICbieten. Daher müssen Sie zunächst die Verfügbarkeit überprüfen:

  • Wenn _POSIX_MONOTONIC_CLOCKein Wert definiert ist, >= 0bedeutet dies, dass dieser CLOCK_MONOTONICverfügbar ist.
  • Wenn dies _POSIX_MONOTONIC_CLOCKdefiniert ist, 0bedeutet dies, dass Sie zusätzlich prüfen sollten, ob es zur Laufzeit funktioniert. Ich empfehle Folgendes sysconf:

    #include <unistd.h>
    
    #ifdef _SC_MONOTONIC_CLOCK
    if (sysconf (_SC_MONOTONIC_CLOCK) > 0) {
        /* A monotonic clock presents */
    }
    #endif
  • Andernfalls wird eine monotone Uhr nicht unterstützt und Sie sollten eine Fallback-Strategie verwenden (siehe unten).

Die Verwendung von clock_gettimeist ziemlich einfach:

  • Holen Sie sich den Zeitwert:

    #include <time.h>
    #include <sys/time.h>
    #include <stdint.h>
    
    uint64_t get_posix_clock_time ()
    {
        struct timespec ts;
    
        if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
            return (uint64_t) (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
        else
            return 0;
    }

    Ich habe die Zeit hier auf Mikrosekunden reduziert.

  • Berechnen Sie die Differenz zum vorherigen Zeitwert auf dieselbe Weise:

    uint64_t prev_time_value, time_value;
    uint64_t time_diff;
    
    /* Initial time */
    prev_time_value = get_posix_clock_time ();
    
    /* Do some work here */
    
    /* Final time */
    time_value = get_posix_clock_time ();
    
    /* Time difference */
    time_diff = time_value - prev_time_value;

Die beste Fallback-Strategie besteht darin, den gettimeofdayAnruf zu verwenden: Er ist nicht monoton, bietet jedoch eine recht gute Auflösung. Die Idee ist die gleiche wie bei clock_gettime, aber um einen Zeitwert zu erhalten, sollten Sie:

#include <time.h>
#include <sys/time.h>
#include <stdint.h>

uint64_t get_gtod_clock_time ()
{
    struct timeval tv;

    if (gettimeofday (&tv, NULL) == 0)
        return (uint64_t) (tv.tv_sec * 1000000 + tv.tv_usec);
    else
        return 0;
}

Auch hier wird der Zeitwert auf Mikrosekunden verkleinert.

SGI IRIX

IRIX hat den clock_gettimeAnruf, aber es fehlt CLOCK_MONOTONIC. Stattdessen hat er seine eigene monotone Taktquelle definiert als CLOCK_SGI_CYCLEdie sollten Sie statt verwenden CLOCK_MONOTONICmit clock_gettime.

Solaris und HP-UX

Solaris verfügt über eine eigene hochauflösende Timer-Schnittstelle, gethrtimedie den aktuellen Timer-Wert in Nanosekunden zurückgibt. Obwohl die neueren Versionen von Solaris möglicherweise vorhanden sind clock_gettime, können Sie sich daran halten, gethrtimewenn Sie alte Solaris-Versionen unterstützen müssen.

Die Verwendung ist einfach:

#include <sys/time.h>

void time_measure_example ()
{
    hrtime_t prev_time_value, time_value;
    hrtime_t time_diff;

    /* Initial time */
    prev_time_value = gethrtime ();

    /* Do some work here */

    /* Final time */
    time_value = gethrtime ();

    /* Time difference */
    time_diff = time_value - prev_time_value;
}

HP-UX fehlt clock_gettime, aber es unterstützt, gethrtimewas Sie auf die gleiche Weise wie unter Solaris verwenden sollten.

BeOS

BeOS verfügt außerdem über eine eigene hochauflösende Timer-Schnittstelle, system_timedie die Anzahl der Mikrosekunden zurückgibt, die seit dem Start des Computers vergangen sind.

Anwendungsbeispiel:

#include <kernel/OS.h>

void time_measure_example ()
{
    bigtime_t prev_time_value, time_value;
    bigtime_t time_diff;

    /* Initial time */
    prev_time_value = system_time ();

    /* Do some work here */

    /* Final time */
    time_value = system_time ();

    /* Time difference */
    time_diff = time_value - prev_time_value;
}

OS / 2

OS / 2 verfügt über eine eigene API zum Abrufen hochpräziser Zeitstempel:

  • Abfrage einer Timerfrequenz (Ticks pro Einheit) mit DosTmrQueryFreq(für GCC-Compiler):

    #define INCL_DOSPROFILE
    #define INCL_DOSERRORS
    #include <os2.h>
    #include <stdint.h>
    
    ULONG freq;
    
    DosTmrQueryFreq (&freq);
  • Fragen Sie den aktuellen Ticks-Wert ab mit DosTmrQueryTime:

    QWORD    tcounter;
    unit64_t time_low;
    unit64_t time_high;
    unit64_t timestamp;
    
    if (DosTmrQueryTime (&tcounter) == NO_ERROR) {
        time_low  = (unit64_t) tcounter.ulLo;
        time_high = (unit64_t) tcounter.ulHi;
    
        timestamp = (time_high << 32) | time_low;
    }
  • Skalieren Sie die Ticks auf die verstrichene Zeit, dh auf Mikrosekunden:

    uint64_t usecs = (prev_timestamp - timestamp) / (freq / 1000000);

Beispielimplementierung

Sie können sich die plibsys- Bibliothek ansehen, die alle oben beschriebenen Strategien implementiert (Details siehe ptimeprofiler * .c).

Alexander Saprykin
quelle
"Es gibt keine richtige ANSI-Lösung mit ausreichender Genauigkeit für das Zeitmessproblem": Es gibt C11 timespec_get: stackoverflow.com/a/36095407/895245
Ciro Santilli 法轮功 冠状 病 六四 事件 23
1
Dies ist immer noch ein falscher Weg, um die Zeit der Codeausführung zu messen. timespec_getist nicht monoton.
Alexander Saprykin
11

timespec_get von C11

Gibt bis zu Nanosekunden zurück, gerundet auf die Auflösung der Implementierung.

Sieht aus wie eine ANSI-Abzocke von POSIX ' clock_gettime.

Beispiel: a printfwird unter Ubuntu 15.10 alle 100 ms ausgeführt:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static long get_nanos(void) {
    struct timespec ts;
    timespec_get(&ts, TIME_UTC);
    return (long)ts.tv_sec * 1000000000L + ts.tv_nsec;
}

int main(void) {
    long nanos;
    long last_nanos;
    long start;
    nanos = get_nanos();
    last_nanos = nanos;
    start = nanos;
    while (1) {
        nanos = get_nanos();
        if (nanos - last_nanos > 100000000L) {
            printf("current nanos: %ld\n", nanos - start);
            last_nanos = nanos;
        }
    }
    return EXIT_SUCCESS;
}

Der C11 N1570 Standardentwurf 7.27.2.5 "Die Funktion timespec_get sagt":

Wenn base TIME_UTC ist, wird das Mitglied tv_sec auf die Anzahl der Sekunden seit einer durch die Implementierung definierten Epoche gesetzt, auf einen ganzen Wert abgeschnitten, und das Mitglied tv_nsec wird auf die ganzzahlige Anzahl von Nanosekunden gesetzt, gerundet auf die Auflösung des Systemtakts. (321)

321) Obwohl ein Struktur-Zeitspezifikationsobjekt Zeiten mit einer Auflösung von Nanosekunden beschreibt, ist die verfügbare Auflösung systemabhängig und kann sogar größer als 1 Sekunde sein.

C ++ 11 hat auch std::chrono::high_resolution_clock: C ++ Plattformübergreifender hochauflösender Timer

Implementierung von glibc 2.21

Kann unter gefunden werden sysdeps/posix/timespec_get.cals:

int
timespec_get (struct timespec *ts, int base)
{
  switch (base)
    {
    case TIME_UTC:
      if (__clock_gettime (CLOCK_REALTIME, ts) < 0)
        return 0;
      break;

    default:
      return 0;
    }

  return base;
}

so klar:

  • Nur TIME_UTCwird derzeit unterstützt

  • Es __clock_gettime (CLOCK_REALTIME, ts)wird an eine POSIX-API weitergeleitet: http://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_getres.html

    Linux x86-64 hat einen clock_gettimeSystemaufruf.

    Beachten Sie, dass dies keine ausfallsichere Mikro-Benchmarking-Methode ist, weil:

    • man clock_gettimesagt, dass diese Maßnahme Diskontinuitäten aufweisen kann, wenn Sie eine Systemzeiteinstellung ändern, während Ihr Programm ausgeführt wird. Dies sollte natürlich ein seltenes Ereignis sein, und Sie können es möglicherweise ignorieren.

    • Dies misst die Wandzeit. Wenn der Planer also beschließt, Ihre Aufgabe zu vergessen, wird sie anscheinend länger ausgeführt.

    Aus diesen Gründen getrusage()könnte es ein besseres, besseres POSIX-Benchmarking-Tool sein, trotz der geringeren maximalen Genauigkeit von Mikrosekunden.

    Weitere Informationen unter: Zeit unter Linux messen - Zeit gegen Uhr gegen getrusage gegen clock_gettime gegen gettimeofday gegen timespec_get?

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
quelle
Dies ist die richtige Antwort ab 2017, auch MSVC hat diese Funktion.
4

Die beste Präzision, die Sie möglicherweise erzielen können, ist die Verwendung des x86-Befehls "rdtsc", der eine Auflösung auf Taktebene bietet (ne muss natürlich die Kosten des rdtsc-Aufrufs selbst berücksichtigen, an denen leicht gemessen werden kann Anwendungsstart).

Der Hauptfang hierbei ist die Messung der Anzahl der Uhren pro Sekunde, die nicht zu schwer sein sollte.

Dunkler Shikari
quelle
3
Möglicherweise müssen Sie auch über die Prozessoraffinität besorgt sein, da Sie auf einigen Computern die RDTSC-Aufrufe möglicherweise an mehr als einen Prozessor senden und deren RDTSC-Zähler möglicherweise nicht synchronisiert sind.
Will Dean
1
Darüber hinaus haben einige Prozessoren keine monoton ansteigende TSC - denken Sie an Energiesparmodi, die die CPU-Frequenz reduzieren. Die Verwendung von RDTSC für alles andere als sehr kurze lokalisierte Timings ist eine SEHR schlechte Idee.
Snemarch
Übrigens ist die von @WillDean erwähnte Kerndrift und die Verwendung von rdtsc für das Timing der Grund, warum eine Reihe von Spielen auf (frühen?) Mehrkern-AMD64-CPUs nicht funktionierte - ich musste mich auf die Single-Core-Affinität meines x2 4400+ beschränken eine Reihe von Titeln.
Snemarch
2

Die akzeptierte Antwort ist gut genug. Aber meine Lösung ist einfacher. Ich teste nur unter Linux und verwende gcc (Ubuntu 7.2.0-8ubuntu3.2) 7.2.0.

Alse verwenden gettimeofday , das tv_secist der Teil der zweiten, und das tv_usecist Mikrosekunden , nicht Millisekunden .

long currentTimeMillis() {
  struct timeval time;
  gettimeofday(&time, NULL);

  return time.tv_sec * 1000 + time.tv_usec / 1000;
}

int main() {
  printf("%ld\n", currentTimeMillis());
  // wait 1 second
  sleep(1);
  printf("%ld\n", currentTimeMillis());
  return 0;
 }

Es druckt:

1522139691342 1522139692342genau eine Sekunde.

LeeR
quelle
-4

Unter Fenstern:

SYSTEMTIME t;
GetLocalTime(&t);
swprintf_s(buff, L"[%02d:%02d:%02d:%d]\t", t.wHour, t.wMinute, t.wSecond, t.wMilliseconds);
Jichao
quelle
1
ist dies ansi C wie gewünscht?
Gyom