#php #performance #micro-optimization
#php #Производительность #микрооптимизация
Вопрос:
Согласно описанию gmmktime() в руководстве по PHP, он использует mktime() внутри. Тем не менее, когда я запускаю следующий код, выполнение цикла mktime занимает чуть менее 9 секунд, в то время как просмотр gmmktime занимает чуть менее 2 секунд. Как это может быть?
<?php
$count = 1000000;
$startTime = microtime(true);
for ($i = 0; $i < $count; $i )
{
mktime();
}
$endTime = microtime(true);
printf("mktime: %.4f secondsn", $endTime - $startTime);
$startTime = microtime(true);
for ($i = 0; $i < $count; $i )
{
gmmktime();
}
$endTime = microtime(true);
printf("gmmktime: %.4f secondsn", $endTime - $startTime);
Вывод:
mktime: 8.6714 seconds
gmmktime: 1.6906 seconds
Ответ №1:
Скорее всего, документация лжет вам о том, как gmmktime()
это реализовано, или это означает, что используется функция C. mktime()
Если мы посмотрим на фактический код, оба gmmktime()
и mktime()
перейдем к внутренней php_mktime
функции, которая принимает gmt
параметр (установленный 1
для gmmktime()
). Если gmt
равно нулю, то он должен выполнить некоторую дополнительную работу ( //
-комментарии, которые я добавил, другие из исходного кода):
/* Initialize structure with current time */
now = timelib_time_ctor();
if (gmt) {
timelib_unixtime2gmt(now, (timelib_sll) time(NULL));
} else {
tzi = get_timezone_info(TSRMLS_C);
now->tz_info = tzi;
now->zone_type = TIMELIB_ZONETYPE_ID;
timelib_unixtime2local(now, (timelib_sll) time(NULL));
}
// ... snip shared code
/* Update the timestamp */
if (gmt) {
// NOTE: Setting the tzi parameter to NULL skips a lot of work in timelib_update_ts
// (and do_adjust_timezone)
timelib_update_ts(now, NULL);
} else {
timelib_update_ts(now, tzi);
}
/* Support for the deprecated is_dst parameter */
if (dst != -1) {
php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "The is_dst parameter is deprecated");
if (gmt) {
/* GMT never uses DST */
if (dst == 1) {
adjust_seconds = -3600;
}
} else {
/* Figure out is_dst for current TS */
timelib_time_offset *tmp_offset;
tmp_offset = timelib_get_time_zone_info(now->sse, tzi);
if (dst == 1 amp;amp; tmp_offset->is_dst == 0) {
adjust_seconds = -3600;
}
if (dst == 0 amp;amp; tmp_offset->is_dst == 1) {
adjust_seconds = 3600;
}
timelib_time_offset_dtor(tmp_offset);
}
}
Я подозреваю, что вы можете обнаружить, что каждый раз, когда вы это делаете mktime()
, он повторно открывает файл описания часового пояса, чтобы прочитать его и получить правильные смещения часового пояса / летнего времени. При использовании gmmktime()
он пропускает это, используя внутренний нулевой часовой пояс для GMT — таким образом, намного быстрее.