vyshkant
@vyshkant
developer

PHP: что быстрее — массивы или объекты?

Добрый день! Есть высоконагруженное приложение, которое выполняет роль посредника: получает данные по сокету, некоторым образом их обрабатывает, и отправляет их дальше в сокет.
Количество входящих данных в критических ситуациях достигает десятков тысяч элементов в секунду, поэтому на счету оказывается каждая тысячная и десятитысячная доля секунды.

Помимо обработки входящих данных, приложение также берет данные из базы и проводит с ними аналогичные операции.

Исторически сложилось, что вся эта схема работает на массивах, т.е. каждый элемент данных представляет собой ассоциативный массив, с которым приходится работать в десятках классов, помня при этом все его ключи, и помня операции, которые к этим данным применяются.

Это катастрофически неудобно, и любой рефакторинг (например, добавление еще одного ключа в массив) приводит к тому, что надо ковырять полпроекта, чтобы внести простую правку.

Неоднократно поднимался вопрос о том, чтобы реализовать данную схему при помощи объектов, в которых бы и хранились данные и методы работы с ними. Однако данное предложение всегда отклоняется со ссылкой на то, что массивы производительнее, а объекты - медленнее.

Мой вопрос: знаете ли вы какие-то исследования, сравнительно описывающие производительность массивов и объектов в PHP? Желательно с примерами и тестами.

Большое спасибо.
  • Вопрос задан
  • 4482 просмотра
Решения вопроса 1
VladimirAndreev
@VladimirAndreev
php web dev
А я тут потестировал немного.

<?php

$test_iteration = 50000000;

function get_rand_data() {
	return [
		'a' => mt_rand(1, 1000),
		'b' => mt_rand(1, 1000),
		'c' => mt_rand(1, 1000),
		'd' => mt_rand(1, 1000),
		'e' => mt_rand(1, 1000),
	];
}

function prepare_data(&$data) {
	return ($data['a'] * $data['b'] / ( $data['c'] * $data['d'] )) / $data['e'];
}

class Data {
	protected $data = [];
	public function __construct(array &$data = []) {
		$this->data = $data;
	}
	public function run() {
		return ($this->data['a'] * $this->data['b'] / ( $this->data['c'] * $this->data['d'] )) / $this->data['e'];	
	}
	public function setData(array &$data) {
		$this->data = $data;
		return $this;
	}
	public function setDataNotReturn(array &$data) {
		$this->data = $data;
	}
}

class StaticData {
	public static function run(&$data) {
		return ($data['a'] * $data['b'] / ( $data['c'] * $data['d'] )) / $data['e'];	
	}
}

function show_delta($end, $start, $text) {
	return $text.': '.round(($end-$start), 5). " seconds\n";
}

$start = microtime(1);
for($i =0; $i<$test_iteration; ++$i) {
	$data = get_rand_data();
	prepare_data($data);
}

echo show_delta(microtime(1), $start, 'Array mode');

$start = microtime(1);
for($i =0; $i<$test_iteration; ++$i) {
	$data = get_rand_data();
	$result = ($data['a'] * $data['b'] / ( $data['c'] * $data['d'] )) / $data['e'];
}

echo show_delta(microtime(1), $start, 'Array run body for mode');

$start = microtime(1);
for($i =0; $i<$test_iteration; ++$i) {
	$data = get_rand_data();
	(new Data($data))->run();
}

echo show_delta(microtime(1), $start, 'Object mode');

$start = microtime(1);
$runner = new Data();
for($i =0; $i<$test_iteration; ++$i) {
	$data = get_rand_data();
	$runner->setData($data)->run();
}

echo show_delta(microtime(1), $start, 'Object mode (v2)');

$start = microtime(1);
$runner = new Data();
for($i =0; $i<$test_iteration; ++$i) {
	$data = get_rand_data();
	$runner->setDataNotReturn($data);
	$runner->run();
}

echo show_delta(microtime(1), $start, 'Object mode (v3)');

$start = microtime(1);
for($i =0; $i<$test_iteration; ++$i) {
	$data = get_rand_data();
	StaticData::run($data);
}

$delta = microtime(1) - $start;

echo show_delta(microtime(1), $start, 'Static object mode');


user@local:~$ php /tmp/test.php
Array mode: 146.38443 seconds
Array run body for mode: 170.97489 seconds
Object mode: 232.68619 seconds
Object mode (v2): 200.46042 seconds
Object mode (v3): 191.89959 seconds
Static object mode: 146.72426 seconds

у меня вот так получилось...
выходит, статический метод объекта практически идентичен массиву с функцией обработки...
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
Stalker_RED
@Stalker_RED
По производительности таких сравнений не припомню, но есть по памяти:
https://habrahabr.ru/post/161629/
https://habrahabr.ru/post/141093/

А вообще, помогут только тесты, причем в вашем окружении и на ваших данных.

Попробуйте посмотреть на это всё профайлером, поискать узкие места. Попробуйте акселераторы, php 7, hhvm.
Можно ли распараллелить обработку?
Может стоит вообще всё выбросить и написать демон на си, или как сейчас модно, на го, например?
Ответ написан
Комментировать
iam_not_a_robot
@iam_not_a_robot
Массивы быстрее, у объектов есть накладные расходы
Ответ написан
Комментировать
@kstyle
быстрее SPL - используйте их, а не "массивы или объекты". вся проблема в универсальности массивов в php. гуглите статью на хабре
Ответ написан
Комментировать
usdglander
@usdglander Куратор тега PHP
Yipee-ki-yay
Согласен. Массивы должны быть быстрее! Но у меня встречный вопрос: а что Вам мешает провести подобное исследование самостоятельно?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы