Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What is going on with this article?
@HirokiTanaka

PHPでAOP的にメソッドの実行時間を計測

More than 5 years have passed since last update.

PHPでAOP的にメソッドの実行時間を計測

概要

  • 特定のインスタンスの呼び出されるメソッド全ての計測をしたい
  • そのクラスのソースコードは(できる限り)かえたくない

こういったものを実現します。

サンプル

code

<html>
<body>
<?php

class PHoge {
  public function getPHoge() {
    return "getPHoge called!!";
  }
}

class Hoge extends PHoge {

    public $hoge;
    public static $hogeStatic = "hoge static";

    public function __construct() {
        $this->hoge = "hoge prop";
        $this->_hoge = "_hoge prop";
    }

    public function getHoge() {
        return $this->_getHoge();
    }

    private function _getHoge() {
        return "_getHoge is called";
    }

    public static function getHogeStatic() {
        return "getHogeStatic is called";
    }
}

class MethodIntercepter {

    private $_instance;
    private static $_className;

    public function __construct($instance) {
        $this->_instance = $instance;
        $ref = new ReflectionClass($instance);
        self::$_className = $ref->getName();
    }

    public function __call($method, $arguments) {

        $timeStart = microtime(true);
        $ret = call_user_func_array(array($this->_instance, $method), $arguments);
        $timePassed = microtime(true) - $timeStart;
        $timePassed *= 1000;        
        $calledMethod = self::$_className . "->{$method}";
        $calledMethodArgs = json_encode($arguments, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        echo "{$calledMethod}({$calledMethodArgs}):{$timePassed}ms<br />";

        return $ret;
    }

    public static function __callStatic($method, $arguments) {

        $timeStart = microtime(true);
        $ret = call_user_func_array(array(self::$_className, $method), $arguments);
        $timePassed = microtime(true) - $timeStart;
        $timePassed *= 1000;
        $calledMethod = self::$_className . "::{$method}";
        $calledMethodArgs = json_encode($arguments, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
        echo "{$calledMethod}({$calledMethodArgs}):{$timePassed}ms<br />";

        return $ret;
    }

    public function __get($key) {

        return $this->_instance->$key;
    }

    public function __set($key, $value) {

        $this->_instance->$key = $value;
    }
}

$hoge = new Hoge();
$hoge = new MethodIntercepter($hoge); // MethodIntercepter でくるむ
echo $hoge->getPHoge() . '<br />';
echo $hoge->getHoge() . '<br />';
echo $hoge->hoge . '<br />';
$hoge->hoge = "hoge prop is changed";
echo $hoge->hoge . '<br />';
echo $hoge::getHogeStatic() . '<br />';
echo Hoge::$hogeStatic . '<br />'; // $hoge::$hogeStatic はできない @see http://stackoverflow.com/questions/1279382/magic-get-getter-for-static-properties-in-php
?>
</body>
</html>

実行結果

スクリーンショット 2015-03-29 17.38.38.png

使い方

  1. MethodIntercepter というクラスを定義します
  2. 計測したいインスタンスを MethodIntercepterでラップします

これだけで、計測したいインスタンスのメソッドの呼び出し全てに対して実行時間を計測できるようになります。
MVCなどで、Controllerに設定されるModelインスタンスに対して適用するなどすると便利です。

6
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
HirokiTanaka
<フリーのソフトウェアエンジニア > <Web系の仕事がメイン(Node/C#/Java/PHP)> <携帯ネイティブアプリ(iOS/Android)などもつくっている> <最近の活動(ReactJSとAngularJSでアプリをつくっている)>

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
6
Help us understand the problem. What is going on with this article?