我有大量用于神经网络的PHP对象,必须对其进行迭代并对其进行一些数学运算。我想知道在类实例上使用关联数组是否更好?
我正在处理3640
对象周围的事物,并且500
最重要的是要在周围的时间(最多)进行迭代,因此任何微优化都会有很大帮助。难免会更快$object['value']
比做起来$object->value
吗?
编辑:所以他们都是一样的。但是我想构造函数会有一些开销吗?无论哪种方式,我都不认为我想用我的漂亮的类来交换脏数组:P
Answers:
根据Quazzle的代码,我运行了下一个代码(5.4.16 Windows 64位):
<?php
class SomeClass {
public $aaa;
public $bbb;
public $ccc;
}
function p($i) {
echo '<pre>';
print_r($i);
echo '</pre>';
}
$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage();
for ($i=0; $i<1000; $i++) {
$z = array();
for ($j=0; $j<1000; $j++) {
$z['aaa'] = 'aaa';
$z['bbb'] = 'bbb';
$z['ccc'] = $z['aaa'].$z['bbb'];
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);
$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage();
for ($i=0; $i<1000; $i++) {
$z = new SomeClass();
for ($j=0; $j<1000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);
$t0 = microtime(true);
$arraysOf=array();
$inicio=memory_get_usage();
for ($i=0; $i<1000; $i++) {
$z = new stdClass();
for ($j=0; $j<1000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>arrays: '.(microtime(true) - $t0)."</p>";
echo '<p>memory: '.($fin-$inicio)."</p>";
p($z);
?>
我得到了下一个结果:
arrays: 1.8451430797577
memory: 460416
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 1.8294548988342
memory: 275696
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 2.2577090263367
memory: 483648
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
PHP 5.4的结论
ps:请注意,如果定义了类,但定义了成员,则使用该类的速度较慢。它还使用更多的内存。 显然,秘密在于定义成员
我从php 5.4更新到了php 5.5(5.5.12 x86 windows)。
arrays: 1.6465699672699
memory: 460400
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 1.8687851428986
memory: 363704
SplFixedArray Object
(
[0] => aaa
[1] => bbb
[2] => aaabbb
)
arrays: 1.8554251194
memory: 275568
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 2.0101680755615
memory: 483656
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
我将此代码用于“概要分析”(1000个实例,1000.000次读/写):
function p($i) {
echo '<pre>';
print_r($i);
echo '</pre>';
}
$t0 = microtime(true);
for ($i=0; $i<1000; $i++) {
$z = array();
for ($j=0; $j<1000; $j++) {
$z['aaa'] = 'aaa';
$z['bbb'] = 'bbb';
$z['ccc'] = $z['aaa'].$z['bbb'];
}
}
echo '<p>arrays: '.(microtime(true) - $t0);
p($z);
$t0 = microtime(true);
for ($i=0; $i<1000; $i++) {
$z = (object) null;
for ($j=0; $j<1000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
}
echo '<p>obj: '.(microtime(true) - $t0);
p($z);
echo '<p> phpversion '.phpversion();
它在托管这些东西的LINUX中输出:
arrays: 1.1085488796234
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
obj: 1.2824709415436
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
phpversion 5.2.17
因此可以得出一个结论:即使在PHP 5.2上,对象也较慢。除非确实需要对象的oop功能,否则不要使用它们。
我在php 7.0.9下使用magallanes的代码:
arrays: 0.19802498817444
memory: 324672
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.18602299690247
memory: 132376
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.1950249671936
memory: 348296
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
和用户php 7.1.3:
arrays: 0.59932994842529
memory: 444920
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.72895789146423
memory: 164512
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.61777496337891
memory: 484416
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
$a=new stdClass(); $a->{1} = 1; $b=(array)$a;
get real ['1'=> 1]。
magallanes的脚本@ PHP 7.3.5
SomeClass Object
最快最轻。Array
1.32倍速度。2.70倍内存stdClass Object
1.65倍速度。2.94x内存。原始输出:
arrays: 0.064794063568115
memory: 444920
Array (
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.048975944519043
memory: 164512
SomeClass Object (
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.081161022186279
memory: 484416
stdClass Object (
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
对于仍然对这个问题感兴趣的任何人:)我在PHP 7.1 Ubuntu x64上运行了Quazzle代码,并得到了以下答案:
arrays: 0.24848890304565
memory: 444920
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.23238587379456
memory: 164512
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
arrays: 0.24422693252563
memory: 484416
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
数组比类对象占用4(!)的内存。
类对象快一些。
stdClass仍然是邪恶的©magallanes :)
您尚未向我们展示了$object->value
工作方式的代码,因为后端可能是一个数组,在理论上就是这种情况使用数组会更快,因为它减少了一个函数调用。与函数调用相比,执行查找的成本可能会很高。如果它是一个变量,则差异将很小,因为PHP中的对象和数组具有非常相似的实现。
如果您正在寻找优化,则需要进行分析以检查大部分时间都在哪里使用。我怀疑将对象更改为数组不会有太大区别。
我看到这是一篇旧文章,所以我想我会对其进行更新。这是我在Zend CE 5.3.21上完成的代码和统计信息,我试图测试整个过程,存储信息并将其取回。
V1:耗时0.83秒
for ($i=1; $i<1000000; $i++) {
$a = get_one();
$b = $a[0];
$b = $a[1];
}
function get_one() {
return array(1,1);
}
V2:耗时3.05秒
for ($i=1; $i<1000000; $i++) {
$a = get_one();
$b = $a->v;
$b = $a->k;
}
function get_one() {
$ret = new test();
$ret->v = 1;
$reb->k = 1;
return $ret;
}
class test {
public $v;
public $k;
}
V3:花费1.98秒(请注意,构造函数提高了性能)
for ($i=1; $i<1000000; $i++) {
$a = get_one();
$b = $a->v;
$b = $a->k;
}
function get_one() {
return new test(1,1);
}
class test {
public $v;
public $k;
public function __construct($v, $k) {
$this->v = $v;
$this->k = $k;
}
}
如果数组和类的性能相同,我认为使用预定义类的对象来存储/传递业务数据将使我们的程序更具逻辑性,代码更具可读性。
如今,有了像Eclipse,Netbean这样的现代思想,很容易知道对象(预定义类)携带的信息是什么,而数组却并非如此
例如:带阵列
function registerCourse(array $student) {
// Right here I don't know how a $student look like unless doing a print_r() or var_dump()
....
}
有对象
class Studen {
private $_name, $_age;
public function getAge() {}
public function getName() {}
..
}
function registerCourse(Studen $student) {
// Right here I just Ctrl+Space $student or click "Student" and I know I can get name or age from it
...
}
好吧,今天我对@magallanes基准感到好奇,因此我对其进行了扩展。我增加了一些for循环,以真正突出显示事物之间的差距。它在Apache 2.4,mod_php和PHP 7.2上运行。
这是一个汇总表,可简化结果:
+---------------------------+---------+-----------------+
| Test | Memory | Time |
+---------------------------+---------+-----------------+
| Array | 2305848 | 9.5637300014496 |
| stdClass | 2505824 | 11.212271928787 |
| SomeClass | 164920 | 3.9636149406433 | <-- *
| AnotherClass | 2563136 | 10.872401237488 |
| SetterClass | 905848 | 59.879059791565 |
| SetterClassDefineReturn | 905792 | 60.484427213669 |
| SetterClassSetFromParam | 745792 | 62.783381223679 |
| SetterClassSetKeyAndParam | 745824 | 72.155715942383 |
+---------------------------+---------+-----------------+
* - Winner winner chicken dinner
下面是修改后的脚本。我想用方法和定义类型来测试设置属性。我很惊讶地发现使用setter方法会对代码产生重大影响。现在,这是一个非常非常具体的性能测试,许多应用程序甚至都不会达到这个目的。但是,如果您有一个处理1000 / reqs / second的站点,该站点具有与1000个对象一起使用的1000个类,则可以看到这可能如何影响性能。
<?php
set_time_limit(500);
class SomeClass {
public $aaa;
public $bbb;
public $ccc;
}
class AnotherClass {
}
class SetterClass {
public $aaa;
public $bbb;
public $ccc;
public function setAAA() {
$this->aaa = 'aaa';
}
public function setBBB() {
$this->bbb = 'bbb';
}
public function setCCC() {
$this->ccc = $this->aaa.$this->bbb;
}
}
class SetterClassDefineReturn {
public $aaa;
public $bbb;
public $ccc;
public function setAAA():void {
$this->aaa = 'aaa';
}
public function setBBB():void {
$this->bbb = 'bbb';
}
public function setCCC():void {
$this->ccc = $this->aaa.$this->bbb;
}
}
class SetterClassSetFromParam {
public $aaa;
public $bbb;
public $ccc;
public function setAAA(string $val): void {
$this->aaa = $val;
}
public function setBBB(string $val): void {
$this->bbb = $val;
}
public function setCCC(string $val): void {
$this->ccc = $val;
}
}
class SetterClassSetKeyAndParam {
public $aaa;
public $bbb;
public $ccc;
public function set(string $key, string $val): void {
$this->{$key} = $val;
}
}
function p($i) {
echo '<pre>';
print_r($i);
echo '</pre>';
echo '<hr>';
}
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<1000; $i++) {
$z = new SomeClass();
for ($j=0; $j<10000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<5000; $i++) {
$z = new AnotherClass();
for ($j=0; $j<5000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<5000; $i++) {
$z = new SetterClass();
for ($j=0; $j<5000; $j++) {
$z->setAAA();
$z->setBBB();
$z->setCCC();
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<5000; $i++) {
$z = new SetterClassDefineReturn();
for ($j=0; $j<5000; $j++) {
$z->setAAA();
$z->setBBB();
$z->setCCC();
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<5000; $i++) {
$z = new SetterClassSetFromParam();
for ($j=0; $j<5000; $j++) {
$z->setAAA('aaa');
$z->setBBB('bbb');
$z->setCCC('aaabbb');
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<5000; $i++) {
$z = new SetterClassSetKeyAndParam();
for ($j=0; $j<5000; $j++) {
$z->set('aaa', 'aaa');
$z->set('bbb', 'bbb');
$z->set('ccc', 'aaabbb');
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<5000; $i++) {
$z = new stdClass();
for ($j=0; $j<5000; $j++) {
$z->aaa = 'aaa';
$z->bbb = 'bbb';
$z->ccc = $z->aaa.$z->bbb;
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
$t0 = microtime(true);
$arraysOf=[];
$inicio=memory_get_usage();
for ($i=0; $i<5000; $i++) {
$z = [];
for ($j=0; $j<5000; $j++) {
$z['aaa'] = 'aaa';
$z['bbb'] = 'bbb';
$z['ccc'] = $z['aaa'].$z['bbb'];
}
$arraysOf[]=$z;
}
$fin=memory_get_usage();
echo '<p>Time Taken (seconds): '.(microtime(true) - $t0).'</p>';
echo '<p>Memory: '.($fin-$inicio).'</p>';
p($z);
结果如下:
Time Taken (seconds): 3.9636149406433
Memory: 164920
SomeClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
-----
Time Taken (seconds): 10.872401237488
Memory: 2563136
AnotherClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
----
Time Taken (seconds): 59.879059791565
Memory: 905848
SetterClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
----
Time Taken (seconds): 60.484427213669
Memory: 905792
SetterClassDefineReturn Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
----
Time Taken (seconds): 62.783381223679
Memory: 745792
SetterClassSetFromParam Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
----
Time Taken (seconds): 72.155715942383
Memory: 745824
SetterClassSetKeyAndParam Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
----
Time Taken (seconds): 11.212271928787
Memory: 2505824
stdClass Object
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)
----
Time Taken (seconds): 9.5637300014496
Memory: 2305848
Array
(
[aaa] => aaa
[bbb] => bbb
[ccc] => aaabbb
)