systemadmin.es > LAMP y web > Llamada stat en PHP a los ficheros de zoneinfo

Llamada stat en PHP a los ficheros de zoneinfo

Para las instalaciones de paquete de PHP es normal ver que se hacen muchas peticiones a los ficheros de las zonas horarias

Lo podemos comprobar con una llamada a date:

echo date( "Y-m-d H:i:s",mktime(0, 0, 0));

Y haciendo un strace al apache:

[pid 14878] open("/var/www/timestamp.php", O_RDONLY|O_LARGEFILE) = 11
[pid 14878] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 14878] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 14878] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 14878] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 14878] mmap2(NULL, 498, PROT_READ, MAP_SHARED, 11, 0) = 0xb6cae000
[pid 14878] munmap(0xb6cae000, 498)     = 0
[pid 14878] close(11)                   = 0
[pid 14878] open("/usr/share/zoneinfo/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 11
[pid 14878] getdents64(11, /* 70 entries */, 32768) = 2032
[pid 14878] getdents64(11, /* 0 entries */, 32768) = 0
[pid 14878] close(11)                   = 0
[pid 14878] stat64("/usr/share/zoneinfo//localtime", {st_mode=S_IFREG|0644, st_size=1725, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//Zulu", {st_mode=S_IFREG|0644, st_size=118, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//WET", {st_mode=S_IFREG|0644, st_size=1873, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//W-SU", {st_mode=S_IFREG|0644, st_size=1448, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//Universal", {st_mode=S_IFREG|0644, st_size=118, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//UTC", {st_mode=S_IFREG|0644, st_size=118, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//US", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//UCT", {st_mode=S_IFREG|0644, st_size=118, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//Turkey", {st_mode=S_IFREG|0644, st_size=2721, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//SystemV", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//Singapore", {st_mode=S_IFREG|0644, st_size=402, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//ROK", {st_mode=S_IFREG|0644, st_size=380, ...}) = 0
[pid 14878] stat64("/usr/share/zoneinfo//ROC", {st_mode=S_IFREG|0644, st_size=724, ...}) = 0
(...)

En una instalación desde código fuente no veremos dicho comportamiento, ya que el fichero de zona horaria esta en el propio PHP. Son las distribuciones que parchean PHP para que use los ficheros del sistema y así tener que evitar mantener las zonas horarias de más de un paquete.

Esto no provoca un problema de rendimiento porque el stats del fichero seguro que va a acabar en la cache, por lo que se el coste va a ser tirando a cero.

Para evitar tener dichas llamadas a stat, podemos instalar el modulo timezonedb:

pecl install timezonedb

Deberemos cargarlo añadiendo la extensión al php.ini:

extension=timezonedb.so

De esta forma devolveremos la configuración de las zonas horarias al PHP que no necesitará hacer la llamada stat para comprobar si ha variado:

[pid 18478] read(10, "HEAD /timestamp.php HTTP/1.1\r\nUser-A"..., 8000) = 83
[pid 18478] gettimeofday({1406798677, 634554}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 634686}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 634779}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 634878}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 634944}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 635057}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 635123}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 635227}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 635293}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 635487}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 635568}, NULL) = 0
[pid 18478] stat64("/var/www/timestamp.php", {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 18478] setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={60, 0}}, NULL) = 0
[pid 18478] rt_sigaction(SIGPROF, {0xb5d14cd0, [PROF], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
[pid 18478] rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0
[pid 18478] umask(077)                  = 022
[pid 18478] umask(022)                  = 077
[pid 18478] getcwd("/", 4095)           = 2
[pid 18478] chdir("/var/www")           = 0
[pid 18478] setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={30, 0}}, NULL) = 0
[pid 18478] time(NULL)                  = 1406798677
[pid 18478] lstat64("/var/www/timezone.php", {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 18478] lstat64("/var/www", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 18478] lstat64("/var", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
[pid 18478] open("/var/www/timestamp.php", O_RDONLY|O_LARGEFILE) = 11
[pid 18478] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 18478] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 18478] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 18478] fstat64(11, {st_mode=S_IFREG|0644, st_size=498, ...}) = 0
[pid 18478] mmap2(NULL, 498, PROT_READ, MAP_SHARED, 11, 0) = 0xb6bac000
[pid 18478] munmap(0xb6bac000, 498)     = 0
[pid 18478] close(11)                   = 0
[pid 18478] time(NULL)                  = 1406798677
[pid 18478] chdir("/")                  = 0
[pid 18478] umask(022)                  = 022
[pid 18478] setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
[pid 18478] setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={0, 0}}, NULL) = 0
[pid 18478] mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6bab000
[pid 18478] mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb6ba9000
[pid 18478] gettimeofday({1406798677, 640714}, NULL) = 0
[pid 18478] gettimeofday({1406798677, 640815}, NULL) = 0
[pid 18478] read(10, 0xb6bad028, 8000)  = -1 EAGAIN (Resource temporarily unavailable)
[pid 18478] writev(10, [{"HTTP/1.1 200 OK\r\nDate: Thu, 31 J"..., 172}], 1) = 172
[pid 18478] gettimeofday({1406798677, 641241}, NULL) = 0
[pid 18478] write(8, "::1 - - [31/Jul/2014:11:24:37 +0"..., 90) = 90
[pid 18478] gettimeofday({1406798677, 641544}, NULL) = 0
[pid 18478] times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1866129947
[pid 18478] gettimeofday({1406798677, 641841}, NULL) = 0
[pid 18478] poll([{fd=10, events=POLLIN}], 1, 5000HTTP/1.1 200 OK

Podremos verificar mediante strace que se van reducir significativamente las llamadas totales a stat:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
42.10    4.627822           5    874136    213420 stat

Pero el tiempo total no se va a ver afectado debido a que dicho fichero estaba en cache:

% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
39.16    4.104965          11    387111    140957 stat

Deja un comentario:

XHTML - Tags permitidos:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>