优化Zend框架

7
我正在尝试让我的应用程序在使用Zend Framework的情况下获得尽可能多的性能。
我正在考虑使用启用了APC的Zend Server,但是我需要先了解一些东西。
使用Zend Server + Zend Framework是否有任何好处,还是只需使用任何普通系统来托管此应用程序即可?
沙米尔

1
小小澄清,Zend Server [http://www.zend.com/en/products/server/] 不是一个 系统,它是一个企业应用程序,运行在 *nix 环境的物理服务器上。作为一名开发人员,我喜欢 Zend Server,特别是当你可以在生产环境中进行调试时。 - Yzmir Ramirez
嗨,我不应该说“系统”。这个词完全错了。所谓的“系统”,其实是指普通的LAMP堆栈。 - bear
不是LAMP :D 只是AMP部分。它可以是WindowsAMP或LinuxAMP ;) - Tomáš Fejfar
我正在Linux服务器上使用这个,所以在这种情况下,它是LAMP。但我仍然喜欢WAMP和WIMP :) - bear
还可以查阅使用Zend Framework开发高负载项目 - David Weinraub
5个回答

26

以下是加快ZF速度的技巧(从上到下尝试):

优化包含路径

  • 首选zend路径
  • 其次是models
  • 最后是rest

使用启用了OPCache的PHP 5.5 [新]

  • 我再强调一遍
  • 获得约50%的增益

缓存表元数据

  • 即使不需要其他缓存,也应该对其进行缓存
  • 我们的一个应用程序在Oracle服务器上的性能提高了约30%;)

使用viewHelpers而不是action() view helper

  • 创建访问模型的view helper
  • 或仅传递来自模型的数据并使用view helpers格式化它们

使用classmap autoloader

  • 自ZF1.11起
  • 最好使用已剥离require_once调用的classmap autoloader

最小化路径堆栈

  • ZF中有很多路径堆栈
    • 表单元素
    • 视图助手
    • 操作助手
  • 每个路径堆栈查找都意味着stat调用=性能损失
  • 默认类随着每个路径的增加而变得越来越昂贵

剥离require_once

使用render()而不是partial()视图助手

  • 不会创建新的视图实例
  • 您需要在主视图中设置超出呈现视图范围的变量!
  • 您还可以使用foreach + render()替换partialLoop()

尽可能缓存所有内容

  • 小块内容需要大量工作,并且很少更改(例如动态菜单)
  • 使用分析器找到易于处理的问题
    • 您认为缓慢的东西可能并不真的很慢
  • 缓存所有可以静态设置缓存的内容
    • 参见手册- Zend_Locale::setCache(), Zend_Currency::setCache(), Zend_Db_Table::setDefaultMetadataCache(), configs...

永远不要使用视图助手action()或操作助手actionStack()

  • 除非绝对必要,否则永远不要使用它们-例如用于复杂的数据输出,但请注意它们带来的性能损失
  • 它们创建整个新的调度循环,并且会降低性能!

禁用viewRenderer

试用我的超级插件

  • 它将包含的类合并为一个长文件以最小化状态调用
  • GitHub获取
    • 它是从EDP的ZF2版本移植而来
    • 但请注意-尚未在生产中进行测试,请谨慎使用
  • 测量性能收益
    • 对我来说,在慢速硬盘驱动器上和其中的所有ZF类中都有损失
    • 尝试使用strip whitespace function最小化它

服务器端文件缩小

  • 对于非常大的文件而言,这是有意义的 - 硬盘驱动器始终是瓶颈
  • 即使微优化有时也有效
    • 具有所有ZF类路径的类映射表是巨大的,当具有“干燥”opcode缓存和受压力的HDD时,去除空格并将长变量替换为$a$b带来了性能增益。

任何opcode缓存当然都是必须的 ;)(APC,ZendOptimizer等)


1
Zend Server包含Optimizer+,这是Zend的opcode优化器和缓存,相当于APC,但根据一些基准测试(例如http://www.zimuel.it/blog/2010/06/benchmarking-zend-server-ce-with-joomla/)来看,在某些情况下更快。因此,虽然您可以在其上启用APC,但实际上并不需要。 - shevron
1
我目前在设计决策上遇到了一个分歧,Tomas。我正在分析是否使用一个带有多个便利方法的基类而不是一个操作助手(我指的是实际的ActionHelper,而不是“Action”Viewhelper或“ActionStack”操作助手)。只是为了明确起见,你可能不会,但如果你是,你是说应该远离Action Helpers吗?如果是这样,为什么?- TIA。 - Aries
2
ActionHelpers的明显优势是它们可以在其他项目中使用;) - Tomáš Fejfar
很好的观点,Mike。但我认为你在大多数情况下在post-redirect-get情况下使用重定向,这是用户期望响应较慢的场景 - 重定向还有一个额外的优势,即删除POST =>没有消息“重新发送表单数据”。 - Tomáš Fejfar
要补充一点,我见过最突出的使用ActionStack的方式是用它来为每个页面渲染菜单和页脚 - 每个在自己的响应段中。一开始我也使用了这种方法,因为它似乎是一个有效的选项(Action View Helper也是如此)。但性能下降教会了我不要使用它! :) - Tomáš Fejfar
显示剩余8条评论

3
无论您运行的是什么样的堆栈,APC 都可以帮助您。任何类型的 OPcode 缓存都可以。
要加速应用程序,第一步是对其进行分析。使用 Xdebug 生成 cachegrind 报告,然后使用类似 kcachegrind 或 webgrind 的工具来解释它。
从使用 Zend Framework 的经验来看,以下是我通常发现的痛点:
- 配置文件计算量很大。一旦您拥有最终的配置对象,请将其缓存! - 文件包含非常昂贵,请尽量将它们减少到最小。如果您为基于反射的内容打开文件很多次,请在那里缓存输出。 - 数据库调用可能很昂贵,但通常不是主要问题,除非它们是中心任务。
页面级缓存会极大地帮助。任何您不需要新鲜数据的地方,请将其缓存。
除此之外,这不再是 Zend Framework 或服务器问题,而开始变得具有架构性。您能异步地处理繁重的任务吗?有时候优化某些东西不值得,但改变用户感知以感觉更快却是值得的。
有趣的想法,前几天我删除了 $i++ 并替换为 ++$i。它从技术上讲更快,但我花费的时间在程序的生命周期内永远无法恢复。您必须在某个地方划线 :)

1

Zend Server是一个非常通用的PHP编译器(来自LAMP或WAMP堆栈中的P),但更加先进,提供了漂亮的GUI来设置所有内容(而不是编辑php.ini),但更重要的是:

  • APC
  • 缓存(数据和页面级别)
  • 作业查询
  • 高级监控与调试

如果您只需要APC,可能会有其他解决方案(我还不知道),但需要APC表明您想要缓存和作业查询...我喜欢它。

不需要使用Zend Framework即可使用它,但您可以使用任何框架(或无框架)。

好的事情是您可以免费尝试ZS的完整功能30天(CE中不提供APC ---->>>> 错误,CE中提供APC)


1

Op-code缓存是在生产环境中运行PHP时您始终想要使用的一个扩展。 Apc是一个op-code缓存和数据缓存扩展,但在Zend服务器中,主要的op-code缓存被称为“Optimizer plus”,我建议在决定使用APC之前比较这两者的性能。 Zend服务器中还有另一个扩展可以完成数据缓存工作。 许多文件包含(例如Zend框架)由于存储在内存中编译,因此使用op-code缓存不再是问题,并且不需要太长时间即可开始使用它们。

使用Zend服务器的完整(付费)版本结合代码跟踪可以实现另一个重大的性能提升,这将为您的应用程序提供有关问题和未优化代码的有价值信息。使用此组合可以非常快速地解决长脚本和函数执行、长DB查询等问题。


0

源代码 这个技巧并不新鲜。它直接来自Zend框架文档:Zend框架性能指南,我使用了其中的一些内容,并省略了一些东西。

使用Zend_Loader并删除所有require_once

我们实际上不能删除所有的require_once语句。我们必须至少有一个require_once来加载Zend_Loader。首先,激活Zend Loader。

require_once 'Zend/Loader.php';
Zend_Loader::registerAutoload();

接下来要做的是删除Zend目录中所有文件中的require_once语句。如果您使用Eclipse PDT,可以使用查找和替换功能。

使用Zend_Cache缓存Zend_Db_Table元数据

当您使用Zend_Db_Table(有时我只使用Zend_Db)时,您会注意到当您尝试从数据库检索数据时,第一个调用的查询是DESCRIBE表。 Zend_Db_Table使用DESCRIBE查询上的信息在SELECT操作上执行其操作。

正如我对我的查询进行了分析,我注意到DESCRIBE查询是最长的查询(在大多数情况下),这意味着您的检索操作存在很大的开销。您有两个选择:

(A) 不使用Zend_Db_Table(改用Zend_Db) (B) 缓存MetaData

在此帖子中,我将使用MetaData缓存。在您的引导文件中,放置以下代码:

//Caching
$frontendOptions = array(
                    'lifetime'                  => 25200,
                    'automatic_serialization'   => true
                    );
$backendOptions  = array(
                     'cache_dir'                => APPLICATION_PATH . '/tmp'
                    );          
$cache = Zend_Cache::factory(
                    'Core',
                    'File',
                    $frontendOptions,
                    $backendOptions
                    );
//Cache table metadata
Zend_Db_Table_Abstract::setDefaultMetadataCache($cache);

缓存插件加载器类文件

在使用插件时,Zend Framework 根据所使用的插件包含多个文件,并进行多次迭代以找到正确的插件并将其包含。使用下面的代码,它创建了一个包含一系列 include_once 语句的列表,以包含这些插件文件。只需将此代码片段包含到您的引导程序中即可。

//Plugin Loader caching
$classFileIncCache = APPLICATION_PATH .  '/data/pluginLoaderCache.php';
if (file_exists($classFileIncCache)) {
    include_once $classFileIncCache;
}
Zend_Loader_PluginLoader::setIncludeFileCache($classFileIncCache);

缓存您的数据

缓存您的数据将是优化中最重要的部分,当重复访问已经缓存的数据时,它将为您节省大量的数据库访问。设置缓存过期时间以及在数据更改时清除缓存非常重要。下面展示了一个简单的缓存。

在您的引导程序上:

//Caching
$frontendOptions = array(
                    'lifetime'                  => 25200,
                    'automatic_serialization'   => true
                    );
$backendOptions  = array(
                     'cache_dir'                => APPLICATION_PATH . '/tmp'
                    );          
$cache = Zend_Cache::factory(
                    'Core',
                    'File',
                    $frontendOptions,
                    $backendOptions
                    );

$registry->set('cache', $dbCache);

这些是基本设置,我认为可能会有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接