问题 使用dumpfiles在CLI模式下使用PHP APC缓存


我最近开始在我们的服务器上使用APC缓存。我们产品最重要的部分之一是CLI(Cron /预定)流程,其性能至关重要。通常,批处理工作包括并行运行一些16-32个进程大约一个小时(它们每隔几分钟“重启”)。

默认情况下,在CLI中使用APC缓存是浪费时间,因为在各个调用之间不保留操作码缓存。但APC也包含 apc_bin_dumpfile() 和 apc_load_dumpfile() 功能。

我认为这两个函数可能用于在CLI模式下使APC高效,方法是在批处理文件之外的某些时间编译,存储在单个转储文件中并让各个进程加载转储文件。

有没有人对这种情况有任何经验,或者你能说明为什么它会起作用还是不起作用?如果可以合理地获得任何重大收益,无论是在内存使用还是性能方面?隐藏在阴影中的陷阱是什么?


11329
2018-04-05 13:17


起源

我没有得到关于为什么在CLI中浪费时间使用APC的部分?你的意思是什么,操作码不能在个别电话之间保留? - N.B.
APC必须在重新启动时重建操作码缓存。当与Web服务器一起使用时,只要计算机处于活动状态,它就会保持活动状态,但在CLI模式下,每个进程都有自己的APC,因此对于每个进程,它必须重建操作码缓存。由于APC通过不必为每个PHP脚本构建操作码来提高性能,因此它几乎否定了您可能获得的任何性能优势。我正在试图解决这个问题。 - Martijn
希望这不会像钝的那样脱落,但你试过了吗?这是一个聪明的解决方法,希望我自己也想过这个。之前我遇到过这样的问题,并且更喜欢使用带有定时循环的Node.js(和永远)。 - Roberto
编译时间在这种情况下真的很重要吗?在这种情况下,与运行时相比,它似乎非常小。 - Wolfgang Stengel
@wolfgang这种情况主要是在内存使用方面。我使用CLI模式并行运行任务(作为穷人的多线程)。每个任务所需的内存越少,我可以并行运行的任务就越多。 - Martijn


答案:


免责声明: 正如APC在CLI中工作一样令人敬畏,并且它非常棒,它同样令人沮丧。使用耐心,耐心,彻底,如果你正在旋转,请远离问题,请记住你正在使用缓存,这就是为什么它似乎什么都不做,它实际上什么都不做。删除转储文件,从基础开始,如果不起作用,请忘记尝试新机器,新操作系统,如果它正在工作制作副本,逐件扩展功能 - 有很多东西不起作用,如果它正在提交或复制,添加另一个部分并再次测试,进行健全性检查,重新检查以前工作过的复制品,陈词滥调与否;如果一开始你没有成功尝试再试一次,你不能继续做同样的事情,期待新的结果。

准备?这就是你一直在等待的:

为cli启用apc

apc.enable-CLI= 1

在每个CLI请求上创建,填充和销毁APC缓存并不理想

   - previous answer by unknown poster since removed.

你是绝对正确的,我们应该解决它吗?

如果您尝试在CLI下使用APC并且未启用它,您将收到警告。

就像是:

PHP Warning:  apc_bin_loadfile(): APC is not enabled, 
              apc_bin_loadfile not available.
PHP Warning:  apc_bin_dumpfile(): APC is not enabled, 
              apc_bin_dumpfile not available.

警告: 我建议你不要在php.ini中启用cli,这不值得沮丧,你会忘记你做了它并且还有许多其他脚本的头疼,相信我不值得,使用启动器脚本代替。 (见下文)

cli中的apc_loadfile和apc_dumpfile

根据评论 mightye php 我们需要禁用 apc.stat 或者你会收到警告

就像是:

PHP Warning:  apc_bin_dumpfile(): Excluding some files from apc_bin_dump[file].  
              Cached files must be included using full path with apc.stat=0. 

启动脚本 - php-apc.sh

我们将使用此脚本启动启用apc的脚本(例如: ./php-apc.sh apc-cli.php而不是改变中的属性 php.ini 直。

#/bin/sh
php -d apc.enable_cli=1 -d apc.stat=0 $1

准备好基本功能了吗?当然你是=)

基本的APC持续存在 - apc-cli.php

<?php
/** check if dump file exists, you don't want to use file_exists */
if (false !== $dump_file = stream_resolve_include_path('apc.dump'))
    /** so where were we lets have a look see shall we */
    if (false !== apc_bin_loadfile($dump_file))
        /** fetch what was stored last run just for fun */
        if (false !== $value = apc_fetch('my.awesome.apc.store'))
            echo "$value from apc\n";

/** store what gets fetched the next run just for fun */
apc_store('my.awesome.apc.store', 'awesome in cli');
/** what a shlep lets not do that all over again shall we */
apc_bin_dumpfile(array(),null,'apc.dump');

注意: 为什么不使用file_exists?因为 file_exists == stat 你看,我们想要获得奖励 apc.stat=0所以;在包含路径内工作;使用绝对路径而不是相对路径 - 由返回 stream_resolve_include_path(); 避免 include_oncerequire_once 使用非 *_once 同行;检查您的统计使用情况,何时 不使用APC(Muchos重要的传感器),借助StreamWrapper echo来调用方法 url_stat; 糟糕:致命的范围超限错误!中止通知线程。看到 url_stat  消息:StreamWrapper导致的错误超出了本讨论的范围。

烟雾测试

使用启动程序执行基本脚本

./php-apc.sh apc-cli.php

一大堆没什么事情发生了我们想要的正确,为什么你还想使用缓存?如果它确实输出了任何东西那么它就不起作用了,抱歉。

应该有一个名为apc.dump的转储文件,看看你能找到它吗?如果你找不到它那就没用了,抱歉。

好我们有转储文件没有错误让我们再次运行它。

./php-apc.sh apc-cli.php

你想看什么:

awesome in cli from apc

成功! =)

PHP中很少有人像工作APC实现那样令人满意。
的nJoy!


13
2017-08-10 20:51



在MAC OS X 10.6.8自定义编译PHP 5.3.14(cli)(内置:2012年7月7日21:32:43) - nickl-
很好的答案!不幸的是,关于统计限制令人遗憾。在我的特殊情况下,我需要包含一个相当大的框架,这些框架充满了包含,所以我可能会为我剪掉我的工作。无论哪种方式,这应该是开始实验的良好基础。 - Martijn
您是否有过在这样的CLI中启用APC实际上是否能提高性能和/或内存使用率的经验? - Martijn
没有任何限制,我试图做的是你想要从spl和apc的非stat优化而不是没有,但一切都将仍然如常。尝试使用include_path和stream_resolve_include_path来获取绝对路径,也许自定义自动加载器也会为您提供服务。如果你需要,我可以挤出一些时间伸出援手。 - nickl-
如果你的内存不足,很可能你有其他的问题,并且没有替代保护,请确保你取消了那些记忆力。分配null即。 $MyHugeCollection = null; 比...快得多 unset($WhatIsTakingSoLong); 但是如果你计划在下一次运行中不必重做长时间的操作,那么无论你对APC会更开心。如果你仍然会做所有事情,那么走这条路几乎没有任何意义。 - nickl-


我会 无疑 不要在CLI中使用它,因为当你重新启动它时,它几乎就像它从未在第一时间运行!

使用APC的更好方法是让它运行 网络服务器本身一直都是,这种方式,它活跃,它实际上会做它应该做的事情!


0
2017-07-24 10:16



显然,我已经在网络服务器上运行了它。但我也想在CLI模式下使用它以减少内存配置文件。默认情况下,APC不会帮助太多,因为它必须重新编译每次运行的文件,但我想知道是否可以使用APC转储文件来跳过编译步骤。 - Martijn
是的,只要在此期间没有变量发生变化,您就可以跳过编译步骤。所以基本上,如果需要重新缓存任何东西,那么你需要重新编译! - Andrew Odendaal


我尝试使用curl和APC.it工作

在CLI中使用这些命令

curl --data "param1=value2" http://testsite.com/test.php

所以它会将数据发布到test.php并将代码写入其中。


-2
2017-09-16 11:12



使用HTTP调用阻止性能关键脚本可能是您可以做的最糟糕的事情。 - nullability