PHP 对象数组不是线性缩放的,而全局数组却可以?

2024-01-12

使用对象内数组作为属性与使用全局 php 数组变量相比,存在一个主要的性能问题,为什么?

为了对这个问题进行基准测试,我创建了以下基准测试,它存储一个越来越大的数组,并以 stdClass 作为节点,运行了两个测试,一个使用类中的数组属性,另一个使用全局数组。

测试代码

ini_set('memory_limit', '2250M');
class MyTest {
    public $storage = [];
    public function push(){
        $this->storage[] = [new stdClass()];
    }
}

echo "Testing Objects".PHP_EOL;
for($size = 1000; $size < 5000000; $size *= 2) {
    $start = milliseconds();
    for ($a=new MyTest(), $i=0;$i<$size;$i++) {
        $a->push();
    }
    $end = milliseconds();
    echo "Array Size $size".PHP_EOL;
    echo $end - $start . " milliseconds to perform".PHP_EOL;
}
echo "================".PHP_EOL;
echo "Testing Array".PHP_EOL;
for($size = 1000; $size < 5000000; $size *= 2) {
    $start = milliseconds();
    for ($a=[], $i=0;$i<$size;$i++) {
        $a[] = [new stdClass()];
    }
    $end = milliseconds();
    echo "Array Size $size".PHP_EOL;
    echo $end - $start . " milliseconds to perform".PHP_EOL;
}

以及令人震惊的结果:

Testing Objects
Array Size 1000
2 milliseconds to perform
Array Size 2000
3 milliseconds to perform
Array Size 4000
6 milliseconds to perform
Array Size 8000
12 milliseconds to perform
Array Size 16000
35 milliseconds to perform
Array Size 32000
97 milliseconds to perform
Array Size 64000
246 milliseconds to perform
Array Size 128000
677 milliseconds to perform
Array Size 256000
2271 milliseconds to perform
Array Size 512000
9244 milliseconds to perform
Array Size 1024000
31186 milliseconds to perform
Array Size 2048000
116123 milliseconds to perform
Array Size 4096000
495588 milliseconds to perform
================
Testing Array
Array Size 1000
1 milliseconds to perform
Array Size 2000
2 milliseconds to perform
Array Size 4000
4 milliseconds to perform
Array Size 8000
8 milliseconds to perform
Array Size 16000
28 milliseconds to perform
Array Size 32000
61 milliseconds to perform
Array Size 64000
114 milliseconds to perform
Array Size 128000
245 milliseconds to perform
Array Size 256000
494 milliseconds to perform
Array Size 512000
970 milliseconds to perform
Array Size 1024000
2003 milliseconds to perform
Array Size 2048000
4241 milliseconds to perform
Array Size 4096000
14260 milliseconds to perform

现在,除了对象调用自身的明显开销之外,当数组变大时,对象数组属性有时会花费 3 - 4 倍的时间来扩展,但标准全局数组变量的情况并非如此。

关于这个问题有什么想法或答案吗?这是否是 PHP 引擎可能存在的错误?


我在 PHP 5.3.9 上测试了你的代码。为此我必须翻译[] to array(),我还必须纠正你的第 12 行:来自$a=new MyTest($size), to $mytest=new MyTest($size)(顺便说一句,构造函数参数被默默地忽略,有趣)。我还添加了这段代码:

echo "================".PHP_EOL;
echo "Testing Function".PHP_EOL;
for($size = 1000; $size < 1000000; $size *= 2) {
    $start = milliseconds();
    for ($a=array(), $i=0;$i<$size;$i++) {
        my_push($a);
    }
    $end = milliseconds();
    echo "Array Size $size".PHP_EOL;
    echo $end - $start . " milliseconds to perform".PHP_EOL;
    echo "memory usage: ".memory_get_usage()." , real: ".memory_get_usage(true).PHP_EOL;
}

function my_push(&$a)
{
   $a[] = array(new stdClass());
}

我在同一点将内存使用情况添加到循环中,添加了unset($mytest);在对象情况之后(以获得更一致的内存日志),并且还将您的 5000000 替换为 1000000,因为我只有 2GB RAM。这就是我得到的:

Testing Objects
Array Size 1000
2 milliseconds to perform
memory usage: 1666376 , real: 1835008
Array Size 2000
5 milliseconds to perform
memory usage: 2063280 , real: 2097152
Array Size 4000
10 milliseconds to perform
memory usage: 2857008 , real: 2883584
Array Size 8000
19 milliseconds to perform
memory usage: 4444456 , real: 4718592
Array Size 16000
44 milliseconds to perform
memory usage: 7619392 , real: 8126464
Array Size 32000
103 milliseconds to perform
memory usage: 13969256 , real: 14417920
Array Size 64000
239 milliseconds to perform
memory usage: 26668936 , real: 27262976
Array Size 128000
588 milliseconds to perform
memory usage: 52068368 , real: 52690944
Array Size 256000
1714 milliseconds to perform
memory usage: 102867104 , real: 103546880
Array Size 512000
5452 milliseconds to perform
memory usage: 204464624 , real: 205258752
================
Testing Array
Array Size 1000
1 milliseconds to perform
memory usage: 18410640 , real: 20709376
Array Size 2000
4 milliseconds to perform
memory usage: 18774760 , real: 20709376
Array Size 4000
7 milliseconds to perform
memory usage: 19502976 , real: 20709376
Array Size 8000
13 milliseconds to perform
memory usage: 20959360 , real: 21233664
Array Size 16000
29 milliseconds to perform
memory usage: 23872176 , real: 24379392
Array Size 32000
61 milliseconds to perform
memory usage: 29697720 , real: 30146560
Array Size 64000
124 milliseconds to perform
memory usage: 41348856 , real: 41943040
Array Size 128000
280 milliseconds to perform
memory usage: 64651088 , real: 65273856
Array Size 256000
534 milliseconds to perform
memory usage: 111255536 , real: 111935488
Array Size 512000
1085 milliseconds to perform
memory usage: 204464464 , real: 205258752
================
Testing Function
Array Size 1000
357 milliseconds to perform
memory usage: 18410696 , real: 22544384
Array Size 2000
4 milliseconds to perform
memory usage: 18774768 , real: 22544384
Array Size 4000
9 milliseconds to perform
memory usage: 19503008 , real: 22544384
Array Size 8000
17 milliseconds to perform
memory usage: 20959392 , real: 22544384
Array Size 16000
36 milliseconds to perform
memory usage: 23872208 , real: 24379392
Array Size 32000
89 milliseconds to perform
memory usage: 29697720 , real: 30146560
Array Size 64000
224 milliseconds to perform
memory usage: 41348888 , real: 41943040
Array Size 128000
529 milliseconds to perform
memory usage: 64651088 , real: 65273856
Array Size 256000
1587 milliseconds to perform
memory usage: 111255616 , real: 111935488
Array Size 512000
5244 milliseconds to perform
memory usage: 204464512 , real: 205258752

正如您所看到的,在函数调用内附加到数组的成本几乎与在原始方法调用内执行附加操作的成本相同(并且具有相同的非线性行为)。可以肯定地说一件事:

正是函数调用消耗了 CPU 时间!

关于非线性行为,只有在超过一定阈值时才会变得非常明显。虽然所有三种情况都具有相同的内存行为(由于不完整的垃圾收集,这仅在本日志中的“普通数组”和“数组内部函数”情况中很明显),但它是“数组内部方法”和“函数内的数组”具有相同执行时间行为的情况。这意味着函数调用本身会导致时间非线性增加。在我看来,可以这么说:

函数调用期间的数据量会影响其持续时间。

为了验证这一点,我替换了所有$a[] with $a[0]以及所有 1000000 和 5000000 (以获得类似的总执行时间)并获得以下输出:

Testing Objects
Array Size 1000
2 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 2000
4 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 4000
8 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 8000
15 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 16000
31 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 32000
62 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 64000
123 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 128000
246 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 256000
493 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 512000
985 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 1024000
1978 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 2048000
3965 milliseconds to perform
memory usage: 1302672 , real: 1572864
Array Size 4096000
7905 milliseconds to perform
memory usage: 1302672 , real: 1572864
================
Testing Array
Array Size 1000
1 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 2000
3 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 4000
5 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 8000
10 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 16000
20 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 32000
40 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 64000
80 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 128000
161 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 256000
322 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 512000
646 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 1024000
1285 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 2048000
2574 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 4096000
5142 milliseconds to perform
memory usage: 1302464 , real: 1572864
================
Testing Function
Array Size 1000
1 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 2000
4 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 4000
6 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 8000
14 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 16000
26 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 32000
53 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 64000
105 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 128000
212 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 256000
422 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 512000
844 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 1024000
1688 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 2048000
3377 milliseconds to perform
memory usage: 1302464 , real: 1572864
Array Size 4096000
6814 milliseconds to perform
memory usage: 1302464 , real: 1572864

请注意,现在时间几乎是完美线性的。当然,现在数组大小固定为 1。另请注意,这三种情况的执行时间差异不如以前那么明显。请记住,最里面的操作在所有情况下都是相同的。

我不会尝试完全解释所有这些(函数调用时的垃圾收集?内存碎片?...?),但我认为我仍然为这里的每个人和我自己收集了一些有用的信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PHP 对象数组不是线性缩放的,而全局数组却可以? 的相关文章

  • 从支付网关重定向回时用户会话丢失

    我已将 Cyber source 配置为我的支付网关 我能够导航到 cybersource 并进行付款 并能够成功重定向回该网站 我也可以取消付款并重定向回我的网站 我收到来自支付网关的响应 但是 用户在从支付网关重定向回来时会被注销 我正
  • Laravel leftJoin 仅右表的最后一条记录

    我是 Laravel 的新手 我有两张桌子 1 产品 2 价格 products id product int p key name varchar prices id price int p key id product int
  • php curl 使用 GET 发送变量 奇怪的结果

    我正在尝试调用远程站点上页面中的网址 决定使用curl 在远程站点上 url 变量显示为 REQUEST Array var1 gt val1 amp var2 gt val2 amp var3 gt val3 被调用的url是 http
  • 免费 PHP 登录库 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • CodeIgniter 自定义库未加载

    我是 CodeIgniter 的新手 并尝试用它开发一个相当简单的应用程序 只是一个用于处理想要娱乐中心通行证的员工的注册的表单 我正在尝试将事物分开以使它们更清晰 这是代码 应用程序 控制器 reccenter php class Rec
  • PHP 通过 SSL 连接到 MS SQL

    我想要实现的目标非常简单 我想通过安全连接从 PHP 脚本连接到外部 MS SQL 数据库 然而 这已被证明是有问题的 到目前为止 经过三个小时的研究 我不知所措 客户端的平台是Ubuntu 这意味着我无法使用SQLSRV 安全连接已经在不
  • 图像随机损坏(但刷新后加载)并显示“资源解释为图像但使用 MIME 类型 text/html 传输”

    我目前正在开发一个简单的 php 网站 问题是 我的整个网站中的图像 发生在所有 php 文件中 随机损坏并显示错误资源解释为图像 但以 MIME 类型 text html 传输但是 如果我尝试多次刷新页面 可以再次加载图像并且错误消失 我
  • 无法访问 localhost/xampp/index.php

    我刚刚安装了 Windows 7 的 XAMPP 控制面板似乎工作正常 我启动了 MySql 和 Apache 我遇到的问题是 当我在浏览器 Google Chrome 中输入 localhost 时 它会将我发送到 http localh
  • PHP WCF 集成

    是不是如果我想支持php客户端访问我的服务 我必须有一个基本的http端点 这是因为php仍然只支持soap 1 1吗 据我所知 自从我使用 PHP 以来已经两年了 情况仍然如此 如果客户端应用程序将使用 PHP 的内置 SoapClien
  • 如何从网站网址中隐藏 .html 扩展名

    我知道这个问题以前曾被问过 但有人知道隐藏 html 扩展名的好方法吗 我已经尝试了许多代码和许多答案https stackoverflow com https stackoverflow com 但我没有看到结果 那是我再问你一次 我有一
  • 如何在 PHP 的 HTML 页面中显示错误消息?

    我有以下登录表单 login php 其中要求输入用户名和密码
  • 将 cookie 设置为在当天结束时过期

    我想设置一个 cookie 并让它在一天结束时过期 这有效 但 24 小时后过期 setcookie route upgrade voted true time 86400 这不起作用 setcookie route upgrade vot
  • 覆盖 FOS 用户包中的“更改密码”模板

    我做了一些研究 遗憾的是找不到任何帮助 因此 我将 FOSUserBundle ChangePasswordAction 渲染到我的模板中 但它显示供应商提供的默认模板 我的渲染控制器的模板 block body h2 Einstellun
  • docker 中的 php Curl 冲突 CURLOPT_FILE 和 CURLOPT_RETURNTRANSFER

    当我使用curl时CURLOPT FILE and CURLOPT RETURNTRANSFER选项 文件为空 没有任何curl错误 fp fopen saveTo w ch curl init fileUrl curl setopt ch
  • 在 foreach 中使用 QueryPath 的多个查找

    我正在使用 QueryPath 和 PHP 这发现 eventdate 没问题 但不会为 dtstart 返回任何内容 qp htmlqp url foreach qp gt find table schedule gt find tr a
  • PHP 中的 -> 和 :: 有什么区别?

    这个东西困扰我好久了 一直找不到 在 php 中使用 和 gt 之间的类有什么区别 让我举个例子 想象一个名为 MyClass 的类 该类中有一个函数 myFunction 使用有什么区别 MyClass myclass new MyCla
  • Jquery一键提交多个同名表单

    我有动态创建的循环表单 我需要一键提交所有表单 我正在遵循下面的代码 你能建议我怎么做吗 谢谢
  • session_start():无法解码会话对象

    我有时在使用 CodeIgniter 时遇到以下问题 错误 2019 03 05 19 57 26 gt 严重性 警告 gt session start 无法解码会话对象 会话已被销毁 system libraries Session Se
  • PHP 拒绝从 var_dump、print 等输出数据

    我目前正在运行 WAMP 服务器 并且在过去的 30 分钟内一直在尝试弄清楚我的项目如何以及为什么不会输出任何指定的 PHP 数据 起初我以为是因为我有一个 htaccess文件的output buffering被禁用 所以我删除了它 仍然
  • 如何在 PHP 5.6 中通过 php.ini 设置“verify_peer_name=false”SSL 上下文选项

    案例 我想打开 SSL 连接localhost而 SSL 证书是 FQDN 的问题 问题 没有进行特殊处理就行 下面的程序失败并显示以下消息 PHP Warning stream socket enable crypto Peer cert

随机推荐

  • 如何使用JavaScript判断目录中是否存在文件?

    如何使用javascript判断目录中是否存在文件 如果它在服务器上 你可以做一个HTTP头 http www w3 org Protocols rfc2616 rfc2616 sec9 html sec9 4通过 Ajax 请求 并查看
  • PhpStorm v2017.3.4 与 Codeception v2.4.0 不兼容

    我正在努力使代码接收与 PhpStorm 一起工作 我已经设置了 CLI 解释器 我还设置了 Codeception 这是 Codeception 的配置 当我从 PhpStorm 运行测试时 我收到以下信息 在左侧 以及右侧的文字 Tes
  • 实现不同类型数组集合的更好方法

    我正在寻找 C 中的半通用数据结构来存储不同整数和浮点类型的数组 在某些情况下 整数是位字段 其中每个位都同等重要 并且不能容忍精度损失 由于 C 类型系统和我对 C 的不熟练 我发现这既困难又混乱 项目 Ethercat周期性数据包到达并
  • 使用 AppCompat 时如何更改 ActionBar 标题字体

    我想将自定义字体应用于 ActionBar 上显示的应用程序标题 以前我没有使用任何支持库和这个解决方案 int titleId getResources getIdentifier action bar title id android
  • 如何创建/在哪里获取多个实例的 Wix Bootstrapper

    我目前正在学习如何使用 WiX 创建 msi 安装程序 但似乎遇到了困难 当我创建一个包含单个环境所需的所有内容的 MSI 时 一切都很好 我有功能和组件 并且可以安装我的 MSI 现在我正处于想要将其转换为 SQL Server 样式安装
  • R 中邻居的空间数据/计算指标

    我有 xBin yBin value 形式的二维空间数据 例如 DT data table x c rep 1 3 rep 2 3 rep 3 3 y rep c 1 2 3 3 value 100 c 1 9 对于每个垃圾箱 我想计算所有
  • 从 JS 文件中获取 Vue

    我对现代前端开发工具还很陌生 我安装了 Nodejs 和 NPM 下载了一些软件包 例如 jquery 并且一切正常 然后我安装了 Webpack 第 2 版 我创建了这个演示配置文件 module exports entry entry
  • 如何实现四个 i8 元素组的高效 _mm256_madd_epi8 点积?

    Intel 提供了一个名为 mm256 madd epi16 的 C 风格函数 基本上 m256i mm256 madd epi16 m256i a m256i b 将 a 和 b 中的压缩有符号 16 位整数相乘 生成中间有符号 32 位
  • 如何同步远程服务器数据库与本地数据库

    我想在期间获取从远程服务器数据库到本地数据库的单个表的所有详细信息页面加载事件或其他一些好的方法 应该作为后端进程发生 任何人都可以帮助我解决这个问题 1 在桌面和 Web 应用程序中创建的单个应用程序 2 当用户在桌面应用程序中注册新客户
  • Quarkus 自定义授权拦截器

    我有一个 Quarkus 微服务 使用 quarkus oidc 和 quarkus keycloak authorization 扩展通过 Keycloak 进行身份验证和授权 我需要另外实现以下两个请求拦截器 过滤器 任何身份验证逻辑启
  • 如何阻止 ejabberd 使用 mnesia [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在尝试建立一个将数据库从崩溃的服务器恢复到新服务器的过程 我的服务器正在运行 Ejabberd 作为 XMPP 服务器 并且我将其配置为使用 po
  • Sublime Text 中 >= 和 <= 运算符的语法高亮显示

    我正在尝试为 Matlab 运算符获得正确的语法突出显示 gt and lt 目前 仅 lt and gt 被突出显示 而不是 但例如 被突出显示 我看过Matlab tmLanguage文件 以及两者 gt and lt 包含在运算符正则
  • 向 CreateThread 传递多个参数

    问题 How to pass具体来说two论点创建线程 http msdn microsoft com en us library ms682453 VS 85 aspx when 参数一 类型SOCKET 论证二 一个接口指针 COM S
  • Django 文件字段编码

    我有一个 django 模型如下 class ExportFile BaseExportFile created timestamp models DateTimeField auto now True editable False dat
  • 使用 d3.js 制作分组条形图

    我是 d3 js 的新手 我发现很难创建分组条形图 但我尝试了一些似乎不正确的方法 我想要 x 轴上的月份和 y 轴上的组数 火星和木星 像这样的东西Link https i stack imgur com VowEA png var sv
  • 在 Jsch 中设置 ASCII 模式

    我需要解决当前遇到的 Unix Windows 文件格式 LF 到 CRLF 问题 我使用的 ftp 客户端是 Jcraft 的 Jsch 在线文档非常简单 尽管我遇到了一个可以设置的标志 SSH FXF TEXT MODE 启用 ASCI
  • 类方法无法访问属性

    我创建了一个像这样的类 function MyClass var myInt 1 MyClass prototype EventHandler function e alert this myInt 不幸的是 this是触发的事件 在我的例
  • 如何将大型多维数组部分写入 HDF5 文件?

    我在 C 中使用 HDF5DotNet 并且有一个非常大的数组 几个 GB 我想将其写入 HDF5 文件 它太大了 无法将整个内容存储在内存中 因此我一次生成它的区域并想将它们写出来 但在读回时仍然让它看起来像一个大数组 我知道 HDF5
  • 背景图像占窗口的 100%(并随之调整大小)

    重复 拉伸和缩放 CSS 背景 https stackoverflow com questions 376253 stretch and scale css background 如何拉伸背景图像以覆盖整个 HTML 元素 https st
  • PHP 对象数组不是线性缩放的,而全局数组却可以?

    使用对象内数组作为属性与使用全局 php 数组变量相比 存在一个主要的性能问题 为什么 为了对这个问题进行基准测试 我创建了以下基准测试 它存储一个越来越大的数组 并以 stdClass 作为节点 运行了两个测试 一个使用类中的数组属性 另