为什么PHP imap_headerinfo()在大邮箱上的运行速度要慢得多?

mil*_*osh 5 php email imap

我做了一些关于使用imap_headerinfo()函数的测试,我对结果感到困惑.

在小邮箱上,获取30条消息的数据需要0.5秒.在具有大约500条消息的邮箱上,大约需要7秒来检索相同数量的消息(30条消息)的数据.

为什么邮箱的大小与检索单个电子邮件的标头所需的时间有关?这是正常的吗?

我用这段代码来测试时间:

$time_start = microtime(true);
for ($i=0; $i < 30; $i++) {
    message_header[$i] = imap_headerinfo($mbox, $i+1);
}
$time = microtime(true) - $time_start;
Run Code Online (Sandbox Code Playgroud)

编辑:

邮箱位于同一帐户中.

我接受了Christian Gollhardt的建议,并测量了对imap_headerinfo()函数的每次调用.

结果甚至更奇怪!首先,然后每隔22次对imap_headerinfo()函数的调用比其他函数多10000次.示例:第一次呼叫大约需要0.39秒,然后其他20次呼叫大约需要0.0001秒,然后第22次呼叫大约需要0.47秒,其他20次呼叫大约需要0.00004,依此类推.

编辑2:

经过一些研究后,还有其他的东西出现了.

如果您使用:

$message_header[$i] = imap_headerinfo($mbox, $i + 1);

每22次呼叫大约需要0.4秒,其他呼叫大约需要0.0001秒.

但是,您会期望得到相同的结果:

$message_header[$i] = imap_headerinfo($mbox, 30 - $i);

但是,在这种情况下,每次通话大约需要0.2秒!

这里唯一的区别是,在第二个示例中,标题是以反向消息顺序(从第30个到第1个)检索的,并且由于某种原因,它会极大地影响操作所需的时间.为什么?

注意:也在gmail帐户上测试过.数字之间的比例完全相同,所以我猜它与服务器无关.

先感谢您!

小智 4

当查看IMAP 模块的 PHP 源代码时,您会发现imap_headerinfo函数正在使用mail_fetchstruct,这是来自 c-client 库的函数。

c-client 的文档解释了mail_fetchstruct函数的工作原理,如下所示:

此函数会获取给定 msgno 的所有结构化信息(信封、内部日期、RFC 822 大小、标志和正文结构),并且在 IMAP 的情况下,最多获取 MAPLOOKAHEAD(IMAP2.H 中的参数)后续信息尚未在缓存中的消息。如果给定 msgno 的信封已在缓存中,则不会进行任何提取。返回此 msgno 的 ENVELOPE 和 BODY。BODY 可能为 NIL,在这种情况下,无法获得有关消息主体结构的信息。

我发现的一个 IMAP 头文件将此前瞻值定义为 20,因此第一次调用该函数会导致它从邮箱中获取 20 条附加邮件。这解释了您观察到的行为:每 22 次调用该函数比所有其他调用花费更多的时间。

如果以相反的顺序获取消息,则会导致库首先加载 21 条消息,从您在函数调用中指定的消息开始。下一个调用检查请求的消息是否已缓存,但事实并非如此,因为它位于先前加载的消息之前,因此缓存将被丢弃并重复该过程。因此,反向循环中的每次调用最多将加载 21 条消息。

但是,这并不能真正解释不同邮箱大小的性能差异。我对这种行为的解释更多的是猜测,而不是准确的研究:c-client 库还将消息号预先映射到适当的 UID。IMAP 标头定义了 1000 的 UID 先行计数。这可以解释一定量的性能损失,但我不明白为什么这会导致如此大的差异,但这是我目前能想到的唯一解释。

在包含 1000 条和 2000 条消息的邮箱上进行尝试可能会更深入地了解此 UID 查找是否与此有关。如果确实如此,500 条消息和 1000 条消息之间的性能应该会显着下降,并且 2000 条消息应该几乎与 1000 条消息一样慢。使用网络嗅探器检查服务器实际请求的数据也可能值得一试。不幸的是,我这里没有合适的测试环境来亲自尝试这一点。