简体   繁体   English

为什么这样做会更好?

[英]Why Does This Perform Better?

So I'm trying to implement an Aspect-Oriented Design into my architecture using debug_backtrace and PHP reflection. 因此,我正在尝试使用debug_backtrace和PHP反射在我的体系结构中实现面向方面的设计。 The design works but I decided to see just how badly it impacts performance so I wrote up the following profiling test. 设计工作正常,但是我决定看看它对性能的影响有多严重,因此我编写了以下性能测试。 The interesting thing is that when the Advisable and NonAdvisable methods do nothing, the impact is about 5 times that for using an advisable method versus using a non-advisable method, but when I increase the complexity of each method (here by increasing the number of iterations to 30 or more), advisable methods perform begin to perform better and continue to increase as the complexity increases. 有趣的是,当AdvisableNonAdvisable方法束手无策,影响约5倍,使用的最好方法与使用非明智的方法,但是当我通过增加的数量增加了每个方法(的复杂性在这里迭代到30个或更多),建议的方法会开始表现更好,并且随着复杂度的增加而继续增加。

Base class: 基类:

abstract class Advisable {

    private static $reflections = array();
    protected static $executions = 25;

    protected static function advise()
    {
        $backtrace = debug_backtrace();
        $method_trace = $backtrace[1];
        $object = $method_trace['object'];
        $function = $method_trace['function'];
        $args = $method_trace['args'];

        $class = get_called_class();

        // We'll introduce this later
        $before = array();
        $around = array();
        $after = array();

        $method_info = array(
            'args' => $args,
            'object' => $object,
            'class' => $class,
            'method' => $function,
            'around_queue' => $around
        );

        array_unshift($args, $method_info);
        foreach ($before as $advice)
        {
            call_user_func_array($advice, $args);
        }

        $result = self::get_advice($method_info);

        foreach ($after as $advice)
        {
            call_user_func_array($advice, $args);
        }

        return $result;
    }

    public static function get_advice($calling_info)
    {
        if ($calling_info['around_queue'])
        {
            $around = array_shift($calling_info['around_queue']);
            if ($around)
            {
                // a method exists in the queue
                return call_user_func_array($around, array_merge(array($calling_info), $calling_info['args']));
            }
        }
        $object = $calling_info['object'];
        $method = $calling_info['method'];
        $class = $calling_info['class'];

        if ($object)
        {
            return null; // THIS IS THE OFFENDING LINE
            // this is a class method
            if (isset(self::$reflections[$class][$method]))
            {
                $parent = self::$reflections[$class][$method];
            }
            else
            {
                $parent = new ReflectionMethod('_'.$class, $method);
                if (!isset(self::$reflections[$class]))
                {
                    self::$reflections[$class] = array();
                }
                self::$reflections[$class][$method] = $parent;
            }
            return $parent->invokeArgs($object, $calling_info['args']);
        }
        // this is a static method
        return call_user_func_array(get_parent_class($class).'::'.$method, $calling_info['args']);
    }
}

An implemented class: 一个实现的类:

abstract class _A extends Advisable
{
    public function Advisable()
    {
        $doing_stuff = '';
        for ($i = 0; $i < self::$executions; $i++)
        {
            $doing_stuff .= '.';
        }
        return $doing_stuff;
    }

    public function NonAdvisable()
    {
        $doing_stuff = '';
        for ($i = 0; $i < self::$executions; $i++)
        {
            $doing_stuff .= '.';
        }
        return $doing_stuff;
    }
}

class A extends _A
{
    public function Advisable()
    {
        return self::advise();
    }
}

And profile the methods: 并介绍方法:

$a = new A();
$start_time = microtime(true);
$executions = 1000000;
for ($i = 0; $i < $executions; $i++)
{
    $a->Advisable();
}
$advisable_execution_time = microtime(true) - $start_time;
$start_time = microtime(true);
for ($i = 0; $i < $executions; $i++)
{
    $a->NonAdvisable();
}
$non_advisable_execution_time = microtime(true) - $start_time;

echo 'Ratio: '.$advisable_execution_time/$non_advisable_execution_time.'<br />';
echo 'Advisable: '.$advisable_execution_time.'<br />';
echo 'Non-Advisable: '.$non_advisable_execution_time.'<br />';
echo 'Overhead: '.($advisable_execution_time - $non_advisable_execution_time);

If I run this test with the complexity at 100 (A::executions = 100), I get the following: 如果我以100(A :: executions = 100)的复杂度运行此测试,则会得到以下结果:

Ratio: 0.289029437803
Advisable: 7.08797502518
Non-Advisable: 24.5233671665
Overhead: -17.4353921413

Any ideas? 有任何想法吗?

You're skipping all of the iterations when you call A's Advisable method... you're overwriting it with one single call to the inherited advise() method. 当您调用A的Advisable方法时,您将跳过所有迭代...仅通过一次调用继承的advisor()方法即可覆盖它。 So, when you add iterations, you're only adding them to the NonAdvisable() call. 因此,添加迭代时,只需将其添加到NonAdvisable()调用中。

method overhead should apply to PHP as well as to Java i guess - "the actual method that is called is determined at run time" => the overhead for shadowed Advisible method is bigger 我认为方法开销应该同时适用于PHP和Java,因为“实际调用的方法是在运行时确定的” =>带阴影的Advisible方法的开销较大

but it would be O(1) instead of Non-Advisable 's O(n) 但是它将是O(1)而不是Non-Advisable的O(n)

Sorry for the bother, I just found the line return null; 抱歉,我刚刚发现该行return null; in the get_advice method before the parent method gets called. 在调用父方法之前,在get_advice方法中。 I hate to answer my own question but it's not really worth someone else searching for it. 我不愿回答自己的问题,但值得别人去寻找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM