CodeIgniter框架性能剖析工具CI_profiling

本篇文章是针对CodeIgniter框架提出了一个性能剖析的工具。可以帮助使用CI的开发者清晰的关注到代码执行过程中详细的耗时信息,以便于进一步排查问题,或者分析系统瓶颈来进行优化。

性能剖析

性能剖析(profile)这个词,我是了解与《高性能MySQL》一书。放到CI框架中,其实就是剖析框架代码在执行过程中的各个操作耗时,这些操作可能是查询数据库、查询缓存、RPC调用或者是自定义的某段代码执行过程。了解了这些操作的耗时,不仅可以排查问题(例如接口查不到数据,就可以将sql很方便的打印出来,看是不是参数有问题),更重要的是可以帮助我们优化程序(例如查找耗时瓶颈并优化、优化sql等等)。

工具原理

CI_profiling的工作过程主要为:

  1. 扩展CI_profiling类库,autoload中初始化该Library;
  2. 在不同的位置打点记录数据(例如框架初始化完成、执行sql之前后);
  3. 在输出内容之前整理打点数据,生成剖析结果并设置到response header中;
  4. 在chrome中接收response header,并打印在console中(通过chrome扩展完成);

工具详解

首先看下Library:

<?php
// 定义类型常量
defined('PROFILING_DB') or define('PROFILING_DB', 1);
defined('PROFILING_CACHE') or define('PROFILING_CACHE', 2);
defined('PROFILING_LOG') or define('PROFILING_LOG', 3);
defined('PROFILING_HTTP') or define('PROFILING_HTTP', 4);
defined('PROFILING_CUSTOMIZED') or define('PROFILING_CUSTOMIZED', 6);
defined('PROFILING_TOTAL') or define('PROFILING_TOTAL', 100);

// 定义时间点常量
defined('PROFILING_START') or define('PROFILING_START', 1);
defined('PROFILING_END') or define('PROFILING_END', 2);

class CiProfiling
{
    // 运行环境,只有在此环境下,才会进行性能剖析
    private $env;
    // 是否输出详细信息
    private $output_detail;
    // 存放db操作相关的数据
    private $db_profiling;
    // 存放缓存操作相关的数据
    private $cache_profiling;
    // 存放日志操作相关的数据
    private $log_profiling;
    // 存放http操作相关的数据
    private $http_profiling;
    // 存放自定义执行区间的数据
    private $customized_profiling;
    // 存放总耗时数据
    private $total_profiling;
    // 是否已输出
    private $outputed;

    // 记录时间点
    public function record($profiling_type, $record_type, $data) {}

    // 检查运行环境
    private function checkEnv($env) {}

    // 剖析运算,得出结果
    public function calculate() {}

    // 将性能剖析结果放入header
    public function setHeader() {}

}

在类库里,我们两个配置:运行环境和是否输出详细内容。运行环境决定是否进行性能分析,而输出详细内容则是输出具体的sql、cache key等信息。
除此之外,定义了一些列数据来存储打点信息。

方法方面,最主要是两个方法:record和calculate。我们会在不同的地方去record数据,例如在DB_Query_Builder里面,我们可以这样写:

		#start profiling
        $sql = $this->_compile_select();
        $CI = &get_instance();
        $CI->ciprofiling->record(PROFILING_DB, PROFILING_START, $sql);

		$result = $this->query($sql);

        #end profiling
        $CI->ciprofiling->record(PROFILING_DB, PROFILING_END, $sql);

这样,在每条sql查询前后,我们就会记录时间点信息,指定记录类型(PROFILING_DB),指定时间点类型(PROFILING_STARTorPROFILING_END),以及将这条sql作为key。接着在输出之前,调用calculate来计算这条sql的耗时:

		foreach ($this->profiling_types as $profiling_type) {
            if (!empty($this->$profiling_type)) {
                foreach ($this->$profiling_type as &$item) {
                    if (empty($item['time1']) || empty($item['time2'])) {
                        // log
                        continue;
                    } else {
                        $item['time'] = round(($item['time2'] - $item['time1']), 2);
                        unset($item['time1']);
                        unset($item['time2']);
                    }
                }
            }
        }

接着将剖析好的数据放入header:

        header('CI-Profiling:' . json_encode(array(
                'db' => $this->db_profiling,
                'cache' => $this->cache_profiling,
                'log' => $this->log_profiling,
                'http' => $this->http_profiling,
                'total' => $this->total_profiling,
                'customized' => $this->customized_profiling,
                'url' => $_SERVER['REQUEST_URI']
            )));

而当response到达客户端时,我编写的chrome插件,会将header中的剖析数据提取出来,展示到console中,如下所示(在基础CI框架之上,写了一条sql用来测试):
在这里插入图片描述

大功告成~

源码位置在:https://gitee.com/hf_wowo/CI_profiling。

猜你喜欢

转载自blog.csdn.net/hfut_wowo/article/details/85460444
今日推荐