[php] PHP 객체 대 배열 — 반복하는 동안 성능 비교

나는 반복하고 몇 가지 수학을 수행해야하는 신경망을위한 엄청난 양의 PHP 객체를 가지고 있습니다. 클래스 인스턴스보다 연관 배열을 사용하는 것이 더 나을지 궁금합니다.

나는 주변의 3640객체를 다루고 있으며 그 500위에 (기껏해야) 시간을 반복 하므로 모든 미세 최적화가 큰 도움이됩니다. 그것은 불가피 할 빠를 것 $object['value']보다 $object->value?

편집 : 그래서 둘 다 동일합니다. 하지만 생성자에 약간의 오버 헤드가있을 것 같습니까? 어느 쪽이든 내 아름다운 수업을 더러운 배열로 바꾸고 싶지 않다고 생각합니다 : P



답변

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에 대한 결론

  1. 클래스는 배열보다 빠릅니다 (하지만 약간).
  2. stdClass는 악합니다.
  3. 클래스는 배열보다 적은 메모리를 사용합니다. (약 30 ~ 40 % 할인 !!)

추신 : 참고로 클래스가 정의되었지만 멤버가 정의되어 있으면이 클래스의 사용이 느립니다. 또한 더 많은 메모리를 사용합니다. 분명히 비밀은 멤버를 정의하는 것입니다.

최신 정보

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. 클래스는 여전히 배열보다 적은 메모리를 사용합니다. (약 30-40 % 감소 !!).
  5. SplFixedArray는 Class를 사용하는 것과 비슷하지만 더 많은 메모리를 사용합니다.


답변

이 코드를 “프로파일 링”(인스턴스 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
)


답변

magallanes의 스크립트 @ PHP 7.3.5

  • SomeClass Object 가장 빠르고 가볍습니다.
  • Array 1.32 배속. 2.70x 메모리.
  • 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;
  }
}