【问题标题】:Why is gmmktime() faster than mktime() when the php manual says that the former uses the latter internally?当 php 手册说前者在内部使用后者时,为什么 gmmktime() 比 mktime() 快?
【发布时间】:2011-10-17 23:17:21
【问题描述】:

根据 PHP 手册中的gmmktime() description,它在内部使用 mktime()。然而,当我运行以下代码时,mktime 循环的运行时间不到 9 秒,而 gmmktime 的运行时间不到 2 秒。这怎么可能?

<?php
$count = 1000000;

$startTime = microtime(true);
for ($i = 0; $i < $count; $i++)
{
  mktime();
}
$endTime = microtime(true);
printf("mktime: %.4f seconds\n", $endTime - $startTime);


$startTime = microtime(true);
for ($i = 0; $i < $count; $i++)
{
  gmmktime();
}
$endTime = microtime(true);
printf("gmmktime: %.4f seconds\n", $endTime - $startTime);

输出:

mktime: 8.6714 seconds
gmmktime: 1.6906 seconds

【问题讨论】:

    标签: php performance micro-optimization


    【解决方案1】:

    很可能,文档在向您撒谎gmmktime() 是如何实现的 - 这意味着 C 函数 mktime() 正在被使用。

    如果我们查看实际代码,gmmktime()mktime() 都传递到内部php_mktime 函数,该函数接受gmt 参数(设置为1 用于gmmktime())。如果gmt 为零,那么它必须做一些额外的工作(//-cmets 我已经添加,其他来自原始代码):

    /* 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 && tmp_offset->is_dst == 0) {
                adjust_seconds = -3600;
            }
            if (dst == 0 && tmp_offset->is_dst == 1) {
                adjust_seconds = +3600;
            }
            timelib_time_offset_dtor(tmp_offset);
        }
    }
    

    我怀疑您可能会发现,每次执行mktime() 时,它都会重新打开时区描述文件以读取它并获取正确的时区/DST 偏移量。通过使用gmmktime(),它可以通过使用内部空时区来跳过该问题——因此,速度要快得多。

    【讨论】:

      猜你喜欢
      • 2022-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      • 2011-11-24
      • 2013-09-06
      相关资源
      最近更新 更多