ООП в PHP, или почему highload разрушает воздушные замки

в 15:10, , рубрики: highload, php, ооп, метки: , ,

В процессе рефакторинга одного проекта, первую итерацию мы написали с душой. ООП, неймспесы, геттеры/сеттеры, и так далее.

В общем, как можно догадаться, оно не взлетело, и вот почему.

На многие вещи в PHP при применении ООП происходит страшный overhead. Вдруг оказывается, что правильные геттеры/сеттеры настолько жрут ресурсы, что неправильные паблик свойства гораздо быстрее, чем можно себе только представить. И еще куча проблем.

Простому тесту и посвящена эта статья, а выводы делать вам самим.

Возьмем простой тестик.

<?php
$profilerEnabled = false;

if ( isset($_GET['debug']) ) {
    ini_set('display_errors', true);
    error_reporting(E_ALL);
    $_SERVER['PROJECT_MODE_DEVELOP'] = 1;
    $_SERVER['adminallow'] = 1;
}

if ( isset($_GET['profile']) ) {
    if ( extension_loaded('xhprof') ) {
        xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
        
        $profilerEnabled = true;
    }
}

//define('APP_ROOT', dirname(dirname(dirname(__FILE__))));
//
//include_once('LSF/Autoload.php');
//
//$app = LSF_App::instance();
//$app->initialize();
//
//LSF2_App_Config::setFromFile(null, APP_ROOT . '/misc/config.ini');

class PrivateTest {
    private $_1;
    private $_2;
    private $_3;
    private $_4;
    private $_5;
    
    public function __construct($one, $two, $three, $four, $five) {
        $this->_1 = $one;
        $this->_2 = $two;
        $this->_3 = $three;
        $this->_4 = $four;
        $this->_5 = $five;
    }
    
    public function get1() {
        return $this->_1;
    }
    
    public function get2() {
        return $this->_2;
    }
    
    public function get3() {
        return $this->_3;
    }
    
    public function get4() {
        return $this->_4;
    }
    
    public function get5() {
        return $this->_5;
    }
}

class PublicTest {
    public $_1;
    public $_2;
    public $_3;
    public $_4;
    public $_5;
    
    public function __construct($one, $two, $three, $four, $five) {
        $this->_1 = $one;
        $this->_2 = $two;
        $this->_3 = $three;
        $this->_4 = $four;
        $this->_5 = $five;
    }
}

$a = 0;

for($i = 1; $i <= 100000; $i++) {
    $object = new PrivateTest(1, 2, 3, 4, 5);
    
    $a += privateGetterTest($object);
}
    
$b = 0;

for($i = 1; $i <= 100000; $i++) {
    $object = new PublicTest(1, 2, 3, 4, 5);
    
    $b += publicGetterTest($object);
}
    
if ( $profilerEnabled ) {
    $data = serialize(xhprof_disable());

    $uniq = uniqid();
    
    $dir = ini_get('xhprof.output_dir');
    
    if ( !$dir ) {
        trigger_error('Unable to save profiler data, please, specify the xhprof.output_dir directive in php.ini', E_USER_WARNING);
    } else {
        if ( !is_dir($dir) ) {
            mkdir($dir, 0777, true);
        }

        $file = fopen($dir.'/'.$uniq.'.xhprof', "w+");

        if ( $file ) {
            fwrite($file, $data);
            fclose($file);
            
            echo "<br><br><b><a href='http://lst222.b.ls1.ru/xhprof/?run={$uniq}' target='_blank'>xhprof</a></b>";
        } else {
            trigger_error('Unable to save profiler data. Could not open file.', E_USER_WARNING);
        }
    }
}

function privateGetterTest($object) {
    $d = $object->get1() +
    $object->get2() + 
    $object->get3() +
    $object->get4() +
    $object->get5();
    
    return $d;
}

function publicGetterTest($object) {
    $d = $object->_1 + 
    $object->_2 +
    $object->_3 +
    $object->_4 +
    $object->_5;
    
    return $d;
}
?>

И вот что получим на выходе

Результаты говорят сами за себя — если хотите крутое ООП + highload, либо пишите просто и местами «неправильно», либо мощные куски переносите на более производительные технологии. Мы решили переносом части логики на уровень хранимок в БД PostgreSQL (9ка), оно масштабируется на ура.

Автор: Cord

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js