#c #performance #time
#c #Производительность #время
Вопрос:
Я говорю о старой школьной функции time(), которая возвращает количество секунд с момента начала эпохи в UTC. Это должно быть монотонным, верно?
В моих тестах (см. Ниже) он работает примерно в 10 раз быстрее, чем clock_gettime с CLOCK_MONOTONIC, поэтому мне было интересно, можно ли его использовать в качестве монотонного таймера для ситуаций, когда мне нужен монотонный таймер с низкой задержкой и низким разрешением. (например, для удаления соединений, которые были на сервере дольше 15 секунд)
Вот код на случай, если вам интересно:
#include <cstdio>
#include <chrono>
#include <time.h>
#include <sys/time.h>
#include <x86intrin.h>
using namespace std;
class Timer {
std::chrono::time_point<std::chrono::steady_clock> start;
public:
inline double t() {
auto end = std::chrono::steady_clock::now();
std::chrono::duration<double> diff = end - start;
return diff.count();
}
inline double milli() { return t() * 1000.0;}
Timer() :start(std::chrono::steady_clock::now()) {}
};
const int nloop = 10000000;
void cpp_steady() {
for (int i=0;i<nloop;i ) {
chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
}
}
void get_tod() {
timeval tv;
for (int i=0;i<nloop;i ) {
gettimeofday(amp;tv, 0);
}
}
void get_clock() {
for (int i=0;i<nloop;i ) {
clock_t t = clock();
}
}
void get_time() {
int x =0;
for (int i=0;i<nloop;i ) {
time_t t = time(0);
x =t*3;
}
fprintf(stderr,"%dn",x);
}
void get_clock_gettime() {
timespec ts;
for (int i=0;i<nloop;i ) {
clock_gettime(CLOCK_MONOTONIC, amp;ts);
}
}
void get_rdtsc() {
for (int i=0;i<nloop;i ) {
__rdtsc();
}
}
void emptyloop() {
int x=0;
for (int i=0;i<nloop;i ) {
x =3*i;
}
fprintf(stderr,"%dn",x);
}
void measure(const char *name, void (*f)()) {
Timer t;
f();
double dur = t.milli();
printf(" %-15s : %.3f msn", name, dur);
}
int main () {
measure("cpp_steady", cpp_steady);
measure("gettimeofday", get_tod);
//measure("clock", get_clock); //too fking slow
measure("time", get_time);
measure("clock_gettime", get_clock_gettime);
measure("rdtsc", get_rdtsc);
measure("empty", emptyloop);
return 0;
}
И вот результат:
./clk_bench 2>/dev/null
cpp_steady : 212.415 ms
gettimeofday : 200.733 ms
time : 19.526 ms
clock_gettime : 197.791 ms
rdtsc : 75.169 ms
empty : 2.821 ms
(Кстати, я знаю, что это всего лишь вопрос нескольких наносекунд и на самом деле не имеет значения, но на самом деле time_t также потребляет меньше памяти и является более переносимым, чем альтернативы …)
Комментарии:
1.
This should be monotonic, right?
Нет.
Ответ №1:
Однозначного ответа нет, за исключением того, что time
он не гарантированно будет монотонным.
Он просто возвращает то, что ядро считает текущим временем. Если есть операционная процедура, гарантирующая, что часы никогда не смогут вернуться назад, и если эти процедуры выполняются, то они должны быть монотонными. Например, в окне Unix, используемом ntpd
для синхронизации времени, часы никогда не должны работать в обратном направлении. Но если администратор (человек с правами администратора на компьютере) видит, что машинное время не является точным, и исправляет его в обратном направлении, тогда любое монотонное предположение будет ложным.
Комментарии:
1. Также будьте осторожны с «секундами с тех пор». Есть как минимум 4 варианта — секунды прыжка выполняются правильно (UTC), секунды прыжка откатываются (в результате чего время, которое происходит во время секунды прыжка, повторяется через 1 секунду); секунды прыжка не существует («секунда» немного длиннее секунды — TAI не UTC);и високосные секунды размазаны (большинство «секунд» — это секунда, но один день в году вы можете получить дополнительные длинные секунды).
Ответ №2:
Кодировка значения, возвращаемого из std::time()
, не указана. Однако в большинстве реализаций он возвращает текущее время работы в секундах с эпохи unix.
Если ваши настенные часы монотонны, то std::time()
они тоже будут монотонными. Однако обычно не гарантируется, что настенные часы будут монотонными. Многие современные системы Linux настраивают свои часы на источники NTP, используя смазывание часов, а не скачок назад, но даже в этом случае пользователь может вмешаться и вручную установить часы в обратном направлении.
Комментарии:
1. Хорошо, но если пользователь — это я, и я не меняю часы, а система — современный Linux, тогда это монотонно, верно?
2. Вам нужно будет проверить, что ваши настенные часы монотонны, это зависит от используемого демона NTP и его конфигурации