【问题标题】:PHP Object Caching performancePHP 对象缓存性能
【发布时间】:2009-06-18 03:51:26
【问题描述】:

在磁盘上缓存 PHP 对象和不缓存有区别吗?如果缓存,对象只会为所有站点访问者创建一次,如果没有,它们将为每个访问者创建一次。这有性能差异还是我会浪费时间这样做?

基本上,归根结底,主要问题是:

内存中的多个对象,每个用户(每个用户都有自己的一组实例化对象)

VS

为所有用户缓存在文件中的单个对象(所有用户使用相同的对象,例如,相同的错误处理程序类、相同的模板处理程序类和相同的数据库句柄类)

【问题讨论】:

    标签: php performance oop caching object


    【解决方案1】:

    要使用这些对象,每个 PHP 脚本都必须反序列化它们。因此,将它们缓存在磁盘上绝对不是为了节省内存——它不会节省内存。

    缓存这些对象的原因是创建对象的成本太高。对于普通的 PHP 对象,情况并非如此。但是,如果对象代表昂贵的数据库查询的结果,或从远程 Web 服务获取的信息,例如,将其缓存在本地可能是有益的。

    基于磁盘的缓存不一定是大赢家。如果您使用 PHP 并关心性能,那么您必须在操作码缓存环境(如 APC 或 Zend 平台)中运行应用程序。这些工具还提供缓存,您可以使用这些缓存将 PHP 对象保存在应用程序中。 Memcached 也是一种流行的应用程序数据快速内存缓存解决方案。

    另外请记住,并非所有 PHP 对象都可以序列化,因此无法将它们保存在缓存中,无论是基于磁盘还是内存中的所有数据。基本上,如果对象包含对 PHP 资源的引用,您可能无法序列化它。

    【讨论】:

    • 我要创建的对象不会从数据库中获取,也不会有任何 PHP 资源。至于 Memcached/Zend,由于我正在开发的软件将用于共享网络托管解决方案的低预算,它可能不会安装 Zend Optimizer 和/或 memcached(这是我依赖磁盘的原因。目前,我没有使用 APC,因为我正在 Windows 上开发)主要问题基本上是:为每次访问的每个用户/访问者实例化多个对象 VS 为所有用户实例化一次的单个对象,但数据被写入磁盘
    • PHP 是“无共享”架构,这意味着必须为每个 PHP 会话实例化对象,即使对象的内容是从磁盘读取的。
    • 我还要说,如果您使用 PHP 编程,唯一 实现良好性能和效率的方法是对代码和数据有效地使用内存缓存。相比之下,磁盘 I/O 的成本如此之高,以至于几乎不能算作缓存。
    • 你是说缓存(按文件)大型和复杂的数据库 SELECT 不值得吗?
    • @Byron:我的意思是一般来说,通过将数据缓存在内存而不是磁盘上,您可以获得数量级的性能优势。
    【解决方案2】:

    在磁盘上缓存 PHP 对象和不缓存有区别吗?

    与所有性能调整一样,您应该衡量自己在做什么,而不是盲目地执行一些您不完全理解的伏都教仪式。 当您在$_SESSION 中保存对象时,PHP 将捕获对象状态并从中生成文件(序列化)。在下一个请求时,PHP 将创建一个新对象并使用此状态重新填充它。这个过程比创建对象要昂贵得多,因为 PHP 必须进行磁盘 I/O 然后解析序列化数据。这必须在读取和写入时都发生。

    一般来说,PHP 被设计为无共享架构。这有利有弊,但试图以某种方式回避它通常不是一个好主意。

    【讨论】:

      【解决方案3】:

      不幸的是,这个问题没有正确的答案。同一服务器上相同网站的相同解决方案可以提供更好的性能,也可以提供更差的性能。这实际上取决于太多因素(应用程序、软件、硬件、配置、服务器负载等)。

      要记住的要点是: - 服务器最慢的部分是硬盘。 - 对象创建比磁盘访问好得多。

      => 尽可能远离 HD 并尽可能将数据缓存在 RAM 中。

      如果您没有性能问题,我建议您什么都不做。

      如果您遇到性能问题:基准测试、基准测试、基准测试。 (找到更好解决方案的唯一真正方法)。

      关于该主题的有趣视频:YouTube Scalability

      【讨论】:

      • 好的,谢谢。我可能会添加一种方法来选择用户是否要使用磁盘缓存。
      【解决方案4】:

      我认为你会浪费时间,除非数据是静态的并且生成起来很复杂。

      假设您有一个表示 ACL(访问控制列表)的对象,该对象说明哪些用户级别对某些资源具有权限。

      填充此 ACL 可能需要相当长的时间,尤其是当数据来自数据库时。缓存的 ACL 可以更快地实例化。

      【讨论】:

        【解决方案5】:

        我使用过缓存 SQL 查询结果和耗时的计算结果,并获得了令人印象深刻的结果。现在,我正在开发一个应用程序,该应用程序从包含超过 200,000 条记录的表中获取超过 200 条数据库记录(其中包含大量 SQL 函数和计算),并根据获取的数据计算每个请求的结果。我使用 Zend Framework 的 Zend_Cache 组件来缓存计算结果,所以下次我不需要:

        1. 连接数据库
        2. 等待数据库服务器找到我的记录,计算我的sql函数,返回结果
        3. 将至少 200 条(甚至可能有 1000 条)记录提取到内存中
        4. 遍历所有这些数据并计算我想要从中得到什么

        我只是这样做:

        1. 调用 Zend_Cache::load() 方法,这将做一些文件读取。

        这将在每个请求上为我节省至少 4-5 秒(非常不准确,我实际上并没有对其进行分析。但性能提升非常明显)

        【讨论】:

          【解决方案6】:

          在某些情况下可能很有用,但需要仔细研究影响和其他类型的性能改进(如数据库查询、数据结构、算法等)。

          您缓存的查询应该是恒定的(并且数量有限)并且数据应该是静态的。为了有效(并且值得),您的硬盘访问需要比您对该数据的数据库查询快得多。

          我曾经通过序列化文件中的缓存对象来使用它,在主页上的相对静态内容上,使用负载重的单实例数据库以 200 次以上的点击/秒,不可避免的查询(在我的水平上)。在该主页上获得了大约 40% 的性能。

          代码 - 从头开始​​开发时 - 非常快速和直接,带有 pile_put/get_contents 和 un/serialize。例如,您可以在查询的 md5 校验和之后命名您的文件。

          【讨论】:

            【解决方案7】:

            将对象缓存在内存中通常比在磁盘上更好:

            http://code.google.com/p/php-object-cache/

            但是,为自己设置基准并比较结果。那是只有你才能确定的。

            【讨论】:

            • 只是想知道您是否有针对此与 APC 之类的基准?
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-07-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-02-15
            相关资源
            最近更新 更多