PHP 5 प्रतिबिंब एपीआई प्रदर्शन




performance reflection (7)

मैं वर्तमान में अपने स्वयं के एमवीसी वेब ढांचे में प्रतिबिंब वर्ग (प्रतिबिंब क्लास और प्रतिबिंब विधि मुख्य रूप से) के उपयोग पर विचार कर रहा हूं, क्योंकि मुझे स्वचालित रूप से नियंत्रक वर्गों को कम करने और किसी भी आवश्यक कॉन्फ़िगरेशन ("कॉन्फ़िगरेशन पर सम्मेलन" दृष्टिकोण) के बिना अपने तरीकों का आह्वान करने की आवश्यकता है।

मैं प्रदर्शन के बारे में चिंतित हूं, भले ही मुझे लगता है कि डेटाबेस अनुरोध वास्तविक PHP कोड की तुलना में बड़ी बाधाओं की संभावना है।

तो, मैं सोच रहा हूं कि किसी के पास प्रदर्शन के दृष्टिकोण से PHP 5 प्रतिबिंब के साथ कोई अच्छा या बुरा अनुभव है।

इसके अलावा, मुझे यह जानकर उत्सुकता होगी कि क्या किसी भी लोकप्रिय PHP ढांचे (सीआई, केक, सिम्फनी, आदि) वास्तव में प्रतिबिंब का उपयोग करते हैं।


इसके अलावा, मुझे यह जानकर उत्सुकता होगी कि क्या किसी भी लोकप्रिय PHP ढांचे (सीआई, केक, सिम्फनी, आदि) वास्तव में प्रतिबिंब का उपयोग करते हैं।

http://framework.zend.com/manual/en/zend.server.reflection.html

"आम तौर पर, यह कार्यक्षमता केवल ढांचे के लिए सर्वर कक्षाओं के डेवलपर्स द्वारा उपयोग की जाएगी।"


एक स्थिर कार्य को 1 मिलियन बार कॉल करने से मेरी मशीन पर ~ 0.31 सेकंड खर्च होंगे। प्रतिबिंब विधि का उपयोग करते समय, इसकी लागत ~ 1.82 सेकंड होती है। इसका मतलब है कि प्रतिबिंब एपीआई का उपयोग करने के लिए ~ 500% अधिक महंगा है।

यह वह कोड है जिसका मैंने उपयोग किया था:

<?PHP

class test
{
    static function f(){
            return;
    }
}

$s = microtime(true);
for ($i=0; $i<1000000; $i++)
{
    test::f('x');
}
echo ($a=microtime(true) - $s)."\n";

$s = microtime(true);
for ($i=0; $i<1000000; $i++)
{
    $rm = new ReflectionMethod('test', 'f');
    $rm->invokeArgs(null, array('f'));
}

echo ($b=microtime(true) - $s)."\n";

echo 100/$a*$b;

जाहिर है, वास्तविक प्रभाव उन कॉलों की संख्या पर निर्भर करता है जिन्हें आप उम्मीद करते हैं


कभी-कभी कॉल_user_func_array () जैसी किसी चीज़ का उपयोग करके आपको वह चाहिए जो आपको चाहिए। पता नहीं कैसे प्रदर्शन अलग है।


कोड पर आधारित @ एलिक्स एक्सेल प्रदान किया गया

तो पूर्णता के लिए मैंने कक्षा में प्रत्येक विकल्प को लपेटने का फैसला किया और लागू होने वाले ऑब्जेक्ट्स के कैशिंग को शामिल किया। यहां परिणाम और कोड थे i7-4710HQ पर PHP 5.6 पर परिणाम

array (
  'Direct' => '5.18932366',
  'Variable' => '5.62969398',
  'Reflective' => '6.59285069',
  'User' => '7.40568614',
)

कोड:

function Benchmark($callbacks, $iterations = 100, $relative = false)
{
    set_time_limit(0);

    if (count($callbacks = array_filter((array) $callbacks, 'is_callable')) > 0)
    {
        $result = array_fill_keys(array_keys($callbacks), 0);
        $arguments = array_slice(func_get_args(), 3);

        for ($i = 0; $i < $iterations; ++$i)
        {
            foreach ($result as $key => $value)
            {
                $value = microtime(true); call_user_func_array($callbacks[$key], $arguments); $result[$key] += microtime(true) - $value;
            }
        }

        asort($result, SORT_NUMERIC);

        foreach (array_reverse($result) as $key => $value)
        {
            if ($relative === true)
            {
                $value /= reset($result);
            }

            $result[$key] = number_format($value, 8, '.', '');
        }

        return $result;
    }

    return false;
}

class foo {
    public static function bar() {
        return __METHOD__;
    }
}

class TesterDirect {
    public function test() {
        return foo::bar($_SERVER['REQUEST_TIME']);
    }
}

class TesterVariable {
    private $class = 'foo';

    public function test() {
        $class = $this->class;

        return $class::bar($_SERVER['REQUEST_TIME']);
    }
}

class TesterUser {
    private $method = array('foo', 'bar');

    public function test() {
        return call_user_func($this->method, $_SERVER['REQUEST_TIME']);
    }
}

class TesterReflective {
    private $class = 'foo';
    private $reflectionMethod;

    public function __construct() {
        $this->reflectionMethod = new ReflectionMethod($this->class, 'bar');
    }

    public function test() {
        return $this->reflectionMethod->invoke(null, $_SERVER['REQUEST_TIME']);
    }
}

$testerDirect = new TesterDirect();
$testerVariable = new TesterVariable();
$testerUser = new TesterUser();
$testerReflective = new TesterReflective();

fputs(STDOUT, var_export(Benchmark(array(
    'Direct' => array($testerDirect, 'test'),
    'Variable' => array($testerVariable, 'test'),
    'User' => array($testerUser, 'test'),
    'Reflective' => array($testerReflective, 'test')
), 10000000), true));

चिंतित मत हो। Xdebug स्थापित करें और सुनिश्चित करें कि बाधा कहाँ है।

प्रतिबिंब का उपयोग करने की लागत है, लेकिन क्या यह मायने रखता है कि आप क्या कर रहे हैं। यदि आप प्रतिबिंब का उपयोग कर नियंत्रक / अनुरोध प्रेषक को लागू करते हैं, तो यह प्रति अनुरोध केवल एक उपयोग है। बिल्कुल नगण्य।

यदि आप प्रतिबिंब का उपयोग करके अपनी ओआरएम परत लागू करते हैं, तो इसे प्रत्येक ऑब्जेक्ट या किसी भी संपत्ति तक पहुंच के लिए उपयोग करें, और सैकड़ों या हजारों ऑब्जेक्ट्स बनाएं, फिर यह महंगा हो सकता है।


मेरे मामले में प्रतिबिंब में यह क्लास विधि को कॉल करने से केवल 230% धीमा है, जो कॉल_user_func फ़ंक्शन के रूप में तेज़ है।


मैंने इन 3 विकल्पों को बेंचमार्क किया (दूसरा बेंचमार्क सीपीयू चक्रों को विभाजित नहीं कर रहा था और 4y पुराना था):

class foo {
    public static function bar() {
        return __METHOD__;
    }
}

function directCall() {
    return foo::bar($_SERVER['REQUEST_TIME']);
}

function variableCall() {
    return call_user_func(array('foo', 'bar'), $_SERVER['REQUEST_TIME']);
}

function reflectedCall() {
    return (new ReflectionMethod('foo', 'bar'))->invoke(null, $_SERVER['REQUEST_TIME']);
}

1,000,000 पुनरावृत्तियों के लिए पूर्ण समय लिया गया:

print_r (बेंचमार्क (सरणी ('directCall', 'variableCall', 'reflectCall'), 1000000));

Array
(
    [directCall] => 4.13348770
    [variableCall] => 6.82747173
    [reflectedCall] => 8.67534351
)

और सापेक्ष समय, 1,000,000 पुनरावृत्तियों के साथ भी (अलग रन):

पीएच () -> डंप (बेंचमार्क (सरणी ('डायरेक्टकॉल', 'वेरिएबलकॉल', 'परिलक्षित कॉल'), 1000000, सच));

Array
(
    [directCall] => 1.00000000
    [variableCall] => 1.67164707
    [reflectedCall] => 2.13174915
)

ऐसा लगता है कि प्रतिबिंब प्रदर्शन 5.4.7 में काफी बढ़ गया था (~ 500% से ~ 213% तक )।

यहां Benchmark() फ़ंक्शन का उपयोग किया गया है यदि कोई भी इस बेंचमार्क को फिर से चलाने के लिए चाहता है:

function Benchmark($callbacks, $iterations = 100, $relative = false)
{
    set_time_limit(0);

    if (count($callbacks = array_filter((array) $callbacks, 'is_callable')) > 0)
    {
        $result = array_fill_keys($callbacks, 0);
        $arguments = array_slice(func_get_args(), 3);

        for ($i = 0; $i < $iterations; ++$i)
        {
            foreach ($result as $key => $value)
            {
                $value = microtime(true);
                call_user_func_array($key, $arguments);
                $result[$key] += microtime(true) - $value;
            }
        }

        asort($result, SORT_NUMERIC);

        foreach (array_reverse($result) as $key => $value)
        {
            if ($relative === true)
            {
                $value /= reset($result);
            }

            $result[$key] = number_format($value, 8, '.', '');
        }

        return $result;
    }

    return false;
}




reflection