PHP Objects vs Arrays - การเปรียบเทียบประสิทธิภาพขณะทำซ้ำ


93

ฉันมีออบเจ็กต์ PHP จำนวนมากสำหรับเครือข่ายประสาทเทียมที่ฉันต้องทำซ้ำและทำการคำนวณทางคณิตศาสตร์ ฉันสงสัยว่าฉันจะใช้อาร์เรย์เชื่อมโยงกับอินสแตนซ์ของคลาสได้ดีกว่าหรือไม่?

ฉันกำลังจัดการกับ3640วัตถุรอบ ๆ ตัวและทำซ้ำไปเรื่อย ๆ500(อย่างดีที่สุด) นอกเหนือจากนั้นดังนั้นการเพิ่มประสิทธิภาพแบบไมโครจะช่วยได้มาก มันจะหลีกเลี่ยงไม่ได้จะเร็วจะทำ$object['value']กว่า$object->value?

แก้ไข:ทั้งคู่เหมือนกัน แต่ฉันเดาว่าจะมีค่าใช้จ่ายเล็กน้อยสำหรับตัวสร้างหรือไม่? ไม่ว่าจะด้วยวิธีใดฉันไม่คิดว่าฉันต้องการแลกเปลี่ยนคลาสที่สวยงามของฉันสำหรับอาร์เรย์สกปรก: P

คำตอบ:


65

ตามรหัสของ Quazzle ฉันรันรหัสถัดไป (5.4.16 windows 64bits):

<?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

  1. คลาสเร็วกว่า Arrays (แต่เล็กน้อย)
  2. stdClass ชั่วร้าย
  3. คลาสใช้หน่วยความจำน้อยกว่าอาร์เรย์ (ลดลงประมาณ 30-40% !!)

ps: เป็นหมายเหตุหากคลาสถูกกำหนด แต่เป็นสมาชิกการใช้คลาสนี้จะช้าลง นอกจากนี้ยังใช้หน่วยความจำมากขึ้น เห็นได้ชัดว่าความลับคือการกำหนดสมาชิก

อัปเดต

ฉันอัปเดตจาก php 5.4 เป็น php 5.5 (หน้าต่าง 5.5.12 x86)

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
)

ข้อสรุปสำหรับ php 5.5

  1. สำหรับอาร์เรย์ PHP 5.5 นั้นเร็วกว่า PHP 5.4 สำหรับวัตถุก็ค่อนข้างเหมือนกัน
  2. คลาสช้ากว่าอาร์เรย์ด้วยการเพิ่มประสิทธิภาพของ PHP 5.5 และอาร์เรย์
  3. stdClass ชั่วร้าย
  4. Class ยังคงใช้หน่วยความจำน้อยกว่า Arrays (น้อยลงประมาณ 30-40% !!).
  5. SplFixedArray คล้ายกับการใช้ Class แต่ใช้หน่วยความจำมากกว่า

ทำได้ดีกับคุณที่ดีครับ จะเป็นการดีที่จะขยายสิ่งนี้ออกไปยังอาร์เรย์ที่ซ้อนกันเป็นต้นไซต์ที่น่าสนใจสำหรับประสิทธิภาพของ PHP อื่น ๆ : phpbench.com php-benchmark-script.comแต่ฉันชอบที่คุณใช้หน่วยความจำเช่นกัน
Heath N

2
ด้วย PHP7 ความแตกต่างระหว่างอาร์เรย์และวัตถุมีความสำคัญมากขึ้น สคริปต์ของคุณแสดงความแตกต่างของรันไทม์ 30% และหน่วยความจำ 60% นั่นเป็นเพียงเครื่องของฉัน แต่ตามหลักทั่วไป: อย่าใช้อาร์เรย์เป็นโครงสร้าง ใช้วัตถุแทน :)
KingCrunch

ออบเจ็กต์ต่างจากคลาสในกรณีนี้หรือไม่?
Matt G

บุ๊กมาร์กสิ่งนี้โดยหวังว่าจะมีการอัปเดต PHP7 และบางทีอาจเป็น PHP8 ที่กำลังจะมีขึ้นเมื่อมี @magallanes
s3c

8

ฉันใช้รหัสนี้สำหรับ "การทำโปรไฟล์" (อินสแตนซ์ 1,000 รายการอ่าน / เขียน 1,000.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 อย่าใช้วัตถุเว้นแต่คุณจะต้องการคุณสมบัติของมันจริงๆ


7
จากผู้ใช้ levans stackoverflow.com/users/1473035/levans : ฉันรันสิ่งนี้ด้วย 5.3.8 และอ็อบเจ็กต์ช้าลง 0.51839280128479 สำหรับอาร์เรย์เทียบกับ 0.85355806350708 สำหรับอ็อบเจ็กต์ ฉันยังรันบน 5.4.13 และได้ผลลัพธ์ตรงกันข้ามซึ่งน่าจะเกิดจากการเพิ่มประสิทธิภาพคลาสที่ทำใน 5.4, 0.6256799697876 สำหรับอาร์เรย์เทียบกับ 0.43650078773499 ดูเหมือนว่าตารางจะเปลี่ยนไปและวัตถุต่างๆก็เป็นทางที่จะไปแล้ว
Jean-Bernard Pellerin

1
คำตอบที่ดีฉันเพิ่งทดสอบกับ XAMPP (Apache) และได้ผลลัพธ์ด้านล่าง: อาร์เรย์: 0.5174868106842 Array ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) obj: 0.72189617156982 stdClass Object ([aaa] => aaa [bbb] => bbb [ccc] => aaabbb) phpversion 5.4.19
ilhnctn

1
ฉันวิ่งบน 5.4.13 ด้วย แต่ตรงกันข้ามกับ Jean-Bernard Pellerin: Arrays: 0.5020840167999 Objects: 1.0378720760345 ดังนั้นฉันจะยังไม่ผูกมัดกับวัตถุ
simontemplar

ฉันทำการเปลี่ยนแปลงบางอย่างในโค้ดและคลาสเร็วกว่า Arrays สำหรับ php 5.4 (5.4.16 32bits Windows) ฉันใส่คำตอบใหม่ที่อธิบายเหตุผล
magallanes

PHP 5.5.11 ผลลัพธ์: อาร์เรย์: 0.17430, Objects: 0.24183
Lex

4

สคริปต์ของ magallanes @ PHP 7.3.5

  • SomeClass Object เร็วและเบาที่สุด
  • Array ความเร็ว1.32x . หน่วยความจำ2.70x
  • stdClass Object ความเร็ว1.65x . หน่วยความจำ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
)

3

ฉันใช้รหัสของ magallanes ภายใต้ php 7.0.9:

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
)                      

1
และอย่าลืม stdClass สามารถใช้คีย์ตัวเลขสตริงจริง ['1' => 1] จะถูกจัดเก็บเป็น [1 => 1] แต่เราสามารถใช้$a=new stdClass(); $a->{1} = 1; $b=(array)$a;get จริง ['1' => 1] ได้
chariothy

2
สรุปได้ว่า .. อาร์เรย์เร็วขึ้น 18% แต่ใช้หน่วยความจำมากถึง 2.7 เท่า
jchook

3

สำหรับใครที่ยังสนใจคำถามนี้ :) ฉันใช้ Quazzle code บน PHP 7.1 Ubuntu x64 และได้รับคำตอบนี้:

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 :)


2

คุณยังไม่ได้แสดงรหัสสำหรับวิธีการ$object->valueทำงานเนื่องจากอาจเป็นไปได้ว่าแบ็กเอนด์เป็นอาร์เรย์ซึ่งในกรณีนี้ในทางทฤษฎีใช้อาร์เรย์จะเร็วกว่าเนื่องจากเกี่ยวข้องกับการเรียกฟังก์ชันน้อยกว่าหนึ่งฟังก์ชัน ค่าใช้จ่ายในการค้นหาอาจจะมากเมื่อเทียบกับการเรียกใช้ฟังก์ชัน หากเป็นตัวแปรจะมีความแตกต่างเพียงเล็กน้อยเนื่องจากวัตถุและอาร์เรย์ใน PHP มีการนำไปใช้งานที่คล้ายคลึงกันมาก

หากคุณกำลังดูการเพิ่มประสิทธิภาพคุณจะต้องทำโปรไฟล์เพื่อตรวจสอบว่าเวลาส่วนใหญ่ถูกใช้ไปที่ไหน ฉันสงสัยว่าการเปลี่ยนวัตถุเป็นอาร์เรย์จะไม่สร้างความแตกต่างที่สำคัญ


ฉันคิดว่าค่าน่าจะเป็นตัวแปรสาธารณะดังนั้น O (1) แน่นอนในขณะที่การค้นหาแฮชอาจไม่เป็น
Filip Ekberg

2

ฉันเห็นว่านี่เป็นโพสต์เก่าดังนั้นฉันจึงคิดว่าจะอัปเดต นี่คือรหัสและสถิติของฉันที่ทำบน 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;
  }
}

2

วันนี้ฉันอยากรู้อยากเห็นโดยอิงจากเกณฑ์มาตรฐานของ @magallanes ดังนั้นฉันจึงขยายมันเล็กน้อย ฉันเพิ่มบางส่วนของลูปเพื่อเน้นช่องว่างระหว่างสิ่งต่างๆ กำลังทำงานบน Apache 2.4, mod_php และ PHP 7.2

นี่คือตารางสรุปเพื่อให้ผลลัพธ์ง่ายขึ้น:

+---------------------------+---------+-----------------+
|           Test            | Memory  |      Time       |
+---------------------------+---------+-----------------+
| Array                     | 2305848 | 9.5637300014496 |
| stdClass                  | 2505824 | 11.212271928787 |
| SomeClass                 |  963640 | 11.558017015457 | <-- *
| 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 ช่วยเพิ่มความนิยมให้กับโค้ด ให้ตอนนี้นี่เป็นการทดสอบประสิทธิภาพที่เฉพาะเจาะจงมากซึ่งแอพจำนวนมากจะไม่ได้รับผลกระทบนี้ แต่ถ้าคุณมีไซต์ที่จัดการ 1,000 / reqs / วินาทีกับ 1,000 คลาสที่ใช้กับออบเจ็กต์ 1,000 รายการคุณจะเห็นว่าสิ่งนี้อาจส่งผลต่อประสิทธิภาพอย่างไร

<?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<5000; $i++) {
    $z = new SomeClass();
    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 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): 11.558017015457

Memory: 963640

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
)


1

คุณสามารถตรวจสอบซอร์สโค้ด PHP เพื่อดูฟีเจอร์ประสิทธิภาพระดับจิ๋วเช่นนั้นได้ตลอดเวลา

แต่ในตอนแรกการไม่ทำ ['value'] จะไม่เร็วขึ้นเพราะ PHP ต้องทำการค้นหาว่าจะหา ['value'] ได้จากที่ใดแม้ว่าการค้นหาแฮชแท็กควรเป็น O (1) ก็ไม่รับประกัน มีค่าใช้จ่ายมากขึ้นเมื่อคุณใช้ดัชนีข้อความ

หากออบเจ็กต์มีเพียง 1 ตัวแปรที่คุณต้องการเข้าถึงซึ่งเป็นค่ามีค่าใช้จ่ายมากกว่าในการใช้ออบเจ็กต์


และคุณคิดว่าคุณสมบัติถูกค้นหาจากที่ไหน? พวกเขาอยู่ในตารางแฮชเช่นกัน ... (แม้ว่าจะเป็นจริงมากหรือน้อยในลำต้น)
Artefacto

0

ถ้าอาร์เรย์และคลาสมีประสิทธิภาพเหมือนกันฉันคิดว่าการใช้อ็อบเจ็กต์ของคลาสที่กำหนดไว้ล่วงหน้าสำหรับการจัดเก็บ / ส่งผ่านข้อมูลทางธุรกิจจะทำให้โปรแกรมของเรามีตรรกะมากขึ้นและโค้ดอ่านได้ง่ายขึ้น

วันนี้ด้วยแนวคิดสมัยใหม่เช่น 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
    ...
}

สิ่งนี้ขัดแย้งกับคำตอบอื่น ๆ ที่พิสูจน์แล้วและไม่มีข้อพิสูจน์ นี่จึงเป็นความเชื่อเชิงอุดมคติมากกว่าคำตอบที่แท้จริง
สโคน

0

เพื่อความเป็นธรรมมันขึ้นอยู่กับประเภทของข้อมูลที่คุณมี ผลลัพธ์ในคำตอบอื่น ๆ ถูกต้อง (มากหรือน้อย) * ฉันจะวางโค้ดทดสอบที่ด้านล่างเพื่อความชัดเจน

สิ่งสำคัญที่นี่คือคุณสามารถประหยัดหน่วยความจำได้พอสมควรหากคุณใช้วัตถุที่กำหนดไว้ล่วงหน้าการแลกเปลี่ยนคือความจริงที่ว่าคุณต้องกำหนดโครงสร้างที่แน่นอน

พิจารณาผลการทดสอบต่อไปนี้:

static obj: 0.04223108291626
memory: 164920
object(staticSet)#1 (3) {
  ["aaa"]=>
  string(3) "aaa"
  ["bbb"]=>
  string(3) "bbb"
  ["ccc"]=>
  string(6) "aaabbb"
}
---------------------------------------
static obj with an additional prop: 0.042968988418579
memory: 524920
object(staticSet2)#1000 (3) {
  ["aaa"]=>
  string(3) "aaa"
  ["bbb"]=>
  string(3) "bbb"
  ["ddd"]=>
  string(6) "aaabbb"
}
---------------------------------------

ฉันอาจจะผิดที่นี่ฉันไม่ได้มองหาแหล่งที่มาของ PHP แต่ฉันเชื่อว่าเท่าที่ PHP เกี่ยวข้องทุกอย่างเป็นอาร์เรย์ วัตถุที่กำหนดไว้ล่วงหน้าเป็นเพียงอาร์เรย์ที่กำหนดไว้อย่างดี ข้อสังเกตที่น่าสนใจคือประเภทค่าไม่มีผลเช่น ค่าสตริงเป็น '1' จะใช้หน่วยความจำจำนวนเท่ากันกับค่าบูลของ true

ทำไม? อย่างที่ฉันได้กล่าวไว้ก่อน PHP คืออาร์เรย์ดังนั้นหากคุณมีวัตถุที่มีฟังก์ชัน setter สิ่งที่ PHP (เวอร์ชันที่เรียบง่าย) ทำคือ:

$objects = ['objectName' => [
    'aaa' => '',
    'bbb' => '',
    'ccc' => '',
    'setValue:f' => function('name', 'value') { ... }
    ]
];

ทุกครั้งที่คุณดำเนินการคุณจะค้นหาคีย์ฟังก์ชันที่ค้นหาชื่อเสารวมถึงการตรวจสอบความถูกต้องสำหรับประเภทของเสา ฯลฯ ในพื้นหลัง การประหยัดหน่วยความจำในออบเจ็กต์ที่กำหนดไว้ล่วงหน้ามาจากการกำหนดอาร์เรย์ของความยาวที่ตั้งไว้ (เป็นไปไม่ได้ใน PHP) แทนที่จะจัดสรรหน่วยความจำส่วนหนึ่ง

สรุป:

วัตถุที่หยุดนิ่ง:เย้! เราประหยัดหน่วยความจำ! แต่ถ้าคุณพยายามเพิ่มสิ่งที่อยู่นอกคำจำกัดความมันก็จะใหญ่ขึ้นแล้ว stdClass

['aaa'] into [['aaa'],['bbb']]

อาร์เรย์:ถ้าคุณเขียนด้วย PHP คุณควรรักพวกเขามากกว่านี้แม้แต่สตริงก็เป็นอาร์เรย์ของอักขระใน PHP

วัตถุ:ออบเจ็กต์มีฟังก์ชันที่ยอดเยี่ยมเป็นวิธีที่ยอดเยี่ยมในการจัดระเบียบรหัสของคุณให้เป็นระเบียบสะอาดเป็นโมดูล แต่อย่างที่ทราบกันดีว่า "มีพลังมหาศาล ... ".

ในที่สุดรหัสทดสอบของฉันและ '*' ดูเหมือนผู้คนจะลืมไปว่าถ้าคุณไม่ล้างตัวแปรของคุณในขณะที่สคริปต์กำลังทำงานอยู่มันจะยังคงอยู่ในหน่วยความจำในขณะที่มันจะไม่ส่งผลกระทบต่อเวลาดำเนินการ (มาก) มันจะส่งผลต่อการวัดหน่วยความจำ ดังนั้นในขณะที่เรียกใช้ unset โปรไฟล์หน่วยความจำ () คือเพื่อนของคุณ

<?php

error_reporting(E_ALL);
ini_set('display_errors',1);

$noOfObjects = 1000;
$noOfOperations = 1000;

class set {
    public function setKey($key, $value) {
        $this->{$key} = $value;
    }
    public function readKey($name) {
        return $this->{$name};
    }
}

class staticSet {
    public string $aaa;
    public string $bbb;
    public string $ccc;
}

class staticSet2 {
    public string $aaa;
    public string $bbb;
}

class staticSet3 {
    public bool $aaa;
    public bool $bbb;
    public bool $ccc;
}

$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = array(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'arrays: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new set(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->setKey('aaa','aaa');
        $z->setKey('bbb','bbb');
        $z->setKey('ccc',$z->readKey('aaa').$z->readKey('bbb'));
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'dynamic obj: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = 'aaa';
        $z->{'bbb'} = 'bbb';
        $z->{'ccc'} = $z->{'aaa'}.$z->{'bbb'};
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet2(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = 'aaa';
        $z->{'bbb'} = 'bbb';
        $z->{'ddd'} = $z->{'aaa'}.$z->{'bbb'};
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj with an additional prop: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime($noOfObjects);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new Ds\Map(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->put('aaa','aaa');
        $z->put('bbb','bbb');
        $z->put('ccc',$z->get('aaa').$z->get('bbb'));
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'Ds\Map: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = '1';
        $z->{'bbb'} = '1';
        $z->{'ccc'} = ($z->{'aaa'} && $z->{'bbb'});
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj with bool values: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = new staticSet3(); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z->{'aaa'} = '1';
        $z->{'bbb'} = '1';
        $z->{'ccc'} = ($z->{'aaa'} && $z->{'bbb'});
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'static obj with defined bool values: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;
$arraysOf=[];
$t0 = microtime(true);
$start=memory_get_usage(); 
for ($i=0; $i<$noOfObjects; $i++) {
    $z = array('aaa' => '','bbb' => '','ccc' => ''); // definition
    for ($j=0; $j<$noOfOperations; $j++) {
        $z['aaa'] = 'aaa';
        $z['bbb'] = 'bbb';
        $z['ccc'] = $z['aaa'].$z['bbb'];
    }
    $arraysOf[]=$z;
}
$end=memory_get_usage();  
echo 'predefined array: '.(microtime(true) - $t0).PHP_EOL;
echo 'memory: '.($end-$start).PHP_EOL;
var_dump($z);
unset($t0,$start,$end,$z,$arraysOf);
echo '---------------------------------------'.PHP_EOL;


echo 'phpversion '.phpversion().PHP_EOL;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.