登录 |

emlog优化(一)——罪恶的缓存

2013年09月28日 下午 56:01 | 作者:

引言

emlog使用文件缓存,将数据序列化后存放到 content/cache/,如果你的blog只有几百篇日志,那么这个缓存还是有效果的,如果用emlog运营商业化应用,添加个上千篇日志,这个缓存设计就反倒成为拖累系统的累赘。

问题原因

来看看 include/lib/cache.php 是怎么读取缓存的:

function readCache($cacheName) {
	if ( $this->{$cacheName.'_cache'} == null ) {
		$cachefile = EMLOG_ROOT . '/content/cache/' . $cacheName . '.php';
		// 如果缓存文件不存在则自动生成缓存文件
		if (!is_file($cachefile) || filesize($cachefile) <= 0) {
				if (method_exists($this, 'mc_' . $cacheName)) {
						call_user_func(array($this, 'mc_' . $cacheName));
				}
		}
		if ($fp = fopen($cachefile, 'r')) {
				$data = fread($fp, filesize($cachefile));
				fclose($fp);
				$this->{$cacheName.'_cache'} = unserialize(str_replace("{$cacheName.'_cache'};
}

fopen文件,str_replace替换保护前缀,然后unserialize数据;
来看看一个8000条日志的blog,产生多少缓存数据:

ls -lhS content/cache/
total 17M
-rw-r--r-- 1 www-data www-data 3.9M Sep 28 23:21 logtags.php
-rw-r--r-- 1 www-data www-data 3.1M Sep 28 23:21 tags.php
-rw-r--r-- 1 www-data www-data 693K Sep 28 23:21 logsort.php
-rw-r--r-- 1 www-data www-data 434K Sep 28 23:21 logalias.php
-rw-r--r-- 1 www-data www-data 7.3K Sep 28 23:21 options.php
-rw-r--r-- 1 www-data www-data 2.7K Sep 28 23:21 record.php
-rw-r--r-- 1 www-data www-data 1.4K Sep 28 23:21 newtw.php
-rw-r--r-- 1 www-data www-data 1.1K Sep 28 23:21 comment.php
-rw-r--r-- 1 www-data www-data  971 Sep 28 23:21 sort.php
-rw-r--r-- 1 www-data www-data  935 Sep 28 23:21 logatts.php
-rw-r--r-- 1 www-data www-data  829 Sep 28 23:21 link.php
-rw-r--r-- 1 www-data www-data  691 Sep 28 23:21 newlog.php
-rw-r--r-- 1 www-data www-data  679 Sep 28 23:21 user.php
-rw-r--r-- 1 www-data www-data  673 Sep 28 23:21 sta.php
-rw-r--r-- 1 www-data www-data  592 Sep 28 23:21 navi.php

缓存文件最大达到了3.9M,反序列化时间长达300~500ms,所以说嘛,不会设计缓存,还不如老老实实用数据库SELECT;

优化

优化的方向?

  1. 更快的反序列化方法,比如json、igbinary、msgpack
  2. 对象持久化:hidef

我选用hidef持久化的方法,在php-fpm启动时一次性载入大数组,每次进程请求直接引用数据对象,无需反序列化。

  1. 安装hidef
    pecl install hidef
  2. 配置hidef
    extension=hidef.so
    [hidef]
    hidef.data_path=/var/www/emlog/content/cache
  3. 修改  include/lib/cache.php
            /**
             * 写入缓存
             */
            function cacheWrite ($cacheData, $cacheName) {
                    // 为hidef写入cache,文件后缀名必须为.data
                    @file_put_contents(EMLOG_ROOT . '/content/cache/' . $cacheName . '.data', $cacheData);
                   // 原写入缓存代码 从略 ……
            }
    
            /**
             * 读取缓存文件
             */
            function readCache($cacheName) {
                    if ( $this->{$cacheName.'_cache'} == null ) {
                            if ( strpos($_SERVER['REQUEST_URI'], 'admin') === false && // 管理后台不使用hidef加速
                                    $cacheVal = hidef_fetch($cacheName) ) { // hidef_fetch 获取缓存目录下对应 ***.data 的数据
                                    if ( in_array($cacheName, array('options')) ) {
                                            $cacheVal = $cacheVal->thaw();
                                    }
                                    $this->{$cacheName.'_cache'} = $cacheVal;
                            } else {
                                    // 原读取缓存代码 从略 ……
                            }
                    }
    
                    return $this->{$cacheName.'_cache'};
            }
  4. Crontab 监控缓存目录更新,自动重载php5-fpm
    * * * * * /usr/local/bin/php5-fpm-reload 

    #!/bin/sh
    # php5-fpm-reload
    md5_new="`ls -l /var/www/emlog/content/cache | md5sum | cut -d ' ' -f1`"
    md5_old="`cat /tmp/cache.md5`"
    
    if [ "$md5_new" != "$md5_old" ]; then
            service php5-fpm reload
            echo $md5_new > /tmp/cache.md5
    fi
  5. 由于hidef将数组作为FrozenArray引用对象保存,这个对象ReadOnly,支持key读取,foreach迭代,不能赋值,unset,不能使用数组函数array_XXX 操作,可以使用thaw()导出为标准Array; emlog大量用到array_search, 写个自定义函数替换掉:
    function _array_search( $needle, $haystack, $strict=false) {
            if ( is_array($haystack) ) return array_search($needle, $haystack, $strict);
            foreach ( $haystack as $_key => $_val ) {
                    $find = $strict ? ($_val === $needle) : ($_val == $needle);
                    if ($find) return $_key;
            }
    }

优化结果

优化前 优化后 Diff Diff%
Incl. Wall Time(microsec)
执行时间(毫秒)
376,113
376 毫秒
8,921
8毫秒
-367,192 -97.6%
Incl.
PeakMemUse(bytes)
峰值内存占用
67,770,496
64Mb
522,056
0.5Mb
-67,248,440 -99.2%

关键路径优化前/后的时间差

评论(9条评论)

  1. buy blade and soul gold…

    I think I should give it a shot!…

  2. u4fifa…

    i love this site so much!…

  3. buy mt 2k16 coins xbox one…

    Do not rush me….

  4. u4fifa.com…

    That’s not the issue….

  5. nba 2k mt coins ps4 sale…

    Today looks great ….

  6. FIFA 17 Comfort Trade…

    Proud of you ….

  7. UPAlbion.com…

    If he shows up, we stick with him….

  8. nba 2k17 mt

    Too bad we must return them.

  9. Buy NBA 2K17 MT PC

    i can discover numerous good answers basically have difficulty!

发表评论

您必须登陆才可以发表评论