Wywołanie tzset()
po rozwidleniu wydaje się być bardzo wolne. Widzę powolność, jeśli najpierw wywołuję tzset()
w procesie nadrzędnym przed rozwidleniem. Moja zmienna środowiskowa TZ
nie jest ustawiona. I dtruss
"Mój program testowy i ujawnił, że proces potomny czyta /etc/localtime
dla każdego wywołania , podczas gdy proces nadrzędny odczytuje go tylko raz. Ten dostęp do pliku wydaje się być źródłem spowolnienia, ale nie byłem w stanie określić, dlaczego uzyskuje dostęp do niego za każdym razem w procesie potomnym.Dlaczego funkcja tzset() jest znacznie wolniejsza po rozwidleniu w systemie Mac OS X?
Oto mój program testowy foo.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
void check(char *msg);
int main(int argc, char **argv) {
check("before");
pid_t c = fork();
if (c == 0) {
check("fork");
exit(0);
}
wait(NULL);
check("after");
}
void check(char *msg) {
struct timeval tv;
gettimeofday(&tv, NULL);
time_t start = tv.tv_sec;
suseconds_t mstart = tv.tv_usec;
for (int i = 0; i < 10000; i++) {
tzset();
}
gettimeofday(&tv, NULL);
double delta = (double)(tv.tv_sec - start);
delta += (double)(tv.tv_usec - mstart)/1000000.0;
printf("%s took: %fs\n", msg, delta);
}
skompilowany i wykonany foo.c tak:
[[email protected] scratch]$ clang -o foo foo.c
[[email protected] scratch]$ env -i ./foo
before took: 0.002135s
fork took: 1.122254s
after took: 0.001120s
Używam Mac OS X 10.10.1 (również powielana w 10.9.5).
Początkowo zauważyłem powolność za pomocą ruby (Time # localtime slow in child process).
Mniejszej: polecam 'difftime (przedawnienia tv.tv_sec, start)' zamiast '(d ouble) (tv.tv_sec - start) '. '(double)' in 'delta + = (double) ...' nie jest potrzebne. – chux
Myślę, że główną przyczyną słabej wydajności jest to, że faktycznie sprawdza, czy plik strefy czasowej nie zmienił ** każdego ** połączenia lokalnego - robi to z mac zachowaniem, jak ustawienie systemu może się zmienić spod niego. Słabe zachowanie się widelca może być skutkiem ubocznym stosowanego mechanizmu notyfikacji zmiany pliku, który nie działa poprawnie w trybie 'fork()' - jest to tylko domniemanie oparte na uruchomieniu kodu za pomocą instrumentów i niektórych metod google. – Petesh
Podobała mi się teoria powiadomień, więc zbadałem trochę więcej i wysłałem odpowiedź poniżej. – Muir