WordPress サイトのパフォーマンスチューニング (3) – 冥府魔道変 –

さて、前回の続き。
すっかり query 数を減らすことに執着してしまった男が、冥府魔道に迷い込んでしまったお話。

他に減らせるコストは無いか?キャッシュできる情報は無いか?しばし黙考。
そうだ!オブジェクトキャッシュでキャッシュされているデータを取っておいて、次に呼び出された時にロードすれば
良いじゃないか?
と言うわけで、wp-settings.php を読んでいると、以下の記述を発見。

if ( file_exists(WP_CONTENT_DIR . '/object-cache.php') )
	require_once (WP_CONTENT_DIR . '/object-cache.php');
else
	require_once (ABSPATH . WPINC . '/cache.php');

おぉ!cache.php を改良して wp-content 直下に object-cache.php と言う名前で置いておけば良いのか。
これなら WordPress のコアコードに手をつけないでイケる。
バージョンアップ時も安心だ。

.これが冥府魔道の入り口だとは、その時は気づきませんでした。

てな訳で、まずは wp-includes/cache.php をコピーしてきて修正。
WP_Object_Cache クラスのコンストラクタを以下の様に修正します。

	/**
	 * Sets up object properties; PHP 5 style constructor
	 *
	 * @since 2.0.8
	 * @return null|WP_Object_Cache If cache is disabled, returns null.
	 */
	function __construct() {
		/**
		 * @todo This should be moved to the PHP4 style constructor, PHP5
		 * already calls __destruct()
		 */
		$cached_file = ABSPATH.'wp-content/cached_text/obj_cached.txt';
		$this->cache = (
			file_exists($cached_file)
			? (array) unserialize(file_get_contents($cached_file))
			: array()
		);
		register_shutdown_function(array(&$this, "__destruct"));
	}

これで、ABSPATH.'wp-content/cached_text/obj_cached.txt' ってファイルがあれば、WP_Object_Cache クラスが生成された時にオブジェクトキャッシュ本体に読み込んでくれます。
で、このファイルにオブジェクトキャッシュの中身を書き出しておけば、最初からオブジェクトキャッシュがある状態で WordPress が開始されるのでDB読み出しが極端に減るはず。

キャッシュファイルの作成は WP_Object_Cache のデストラクタに書いておけばいいでしょう。

	/**
	 * Will save the object cache before object is completely destroyed.
	 *
	 * Called upon object destruction, which should be when PHP ends.
	 *
	 * @since  2.0.8
	 *
	 * @return bool True value. Wont be used by PHP
	 */
	function __destruct() {
		$cached_file = ABSPATH.'wp-content/cached_text/obj_cached.txt';
		$write_cache = false;
		if (!file_exists($cached_file))
			$write_cache = true;
		elseif(time() + (30 * 60) < fileatime($cached_file))
			$write_cache = true;

		if ($write_cache) {
			if (file_exists($cached_file))
				@unlink($cached_file);
			$handle = fopen($cached_file, 'w');
			fwrite($handle, serialize($this->cache));
			fclose($handle);
			unset($cache);
		}

		return true;
	}

これで30分に一度キャッシュを書き出してくれます。

で、これやった結果 query数が、どうなったかというと

  • トップページ 69 queries. → 34 queries.
  • シングルページ 35 queries. → 14 queries.

我が軍は圧倒的じゃないか!労せずしてここまで query 数を減らせるとは!

それもそのはず、このオブジェクトキャッシュには wp_options やら wp_posts やら wp_users やらのテーブルのデータが詰まっていて、一度DBにアクセスしたら、同じテーブルにはアクセスしないようにするためのモノだからです。
で、それを次回起動時にも最初からオブジェクトキャッシュに持てば、DBアクセスしないでもイケるところまでイケるはず
理論上は。

実は、WordPress でのオブジェクトキャッシュの制御が、かなりタコかったのです。
DBの内容を変更したのにオブジェクトキャッシュの情報は変更していなかったり、オブジェクトキャッシュが有るのにキャッシュを使用しないでテーブルを直接操作したりされることが結構頻繁にあるのです。
設計の古いプラグインやら、オブジェクトキャッシュが採用される前の WordPress のコードやらが足を引っ張ってくれます。
毎回、処理終了時にはオブジェクトキャッシュが破棄されているので正常に動作していますが、これを毎回使いまわすには問題が山積み。

そんなわけで、この情報をキャッシュして次回起動時に流用すると、不整合が起きて大変な事になる場合も。
全てのコードを精査しないと使えない、かなりリスキーなチューニングでした。

WordPress サイトのパフォーマンスチューニング (3) – 冥府魔道変 –」への4件のフィードバック

  1. J君

    J君です。
    J君のほうにも使えるようになったらな!と少し思いました。
    速度というより、意地です。びんさんに勝ちたい!
    ただ、SAKURAの現状を見て、全く問題はありません。前はCORESERVER.JPでしたがDBがおかしくなって。。。15GBになったとたん、DBが・・・

    でもでも、びんさんには...勝ちたいと思うのです。もし、J君のほうにも適応が出来るレベルにありましたら、教えていただけると嬉しいです。
    あはは、やはりPopularity Contestの影響が大きいのでしょうか?
    いずれにしても、師匠に続きますので、何かありましたらどうぞお願いします。

    返信
  2. をかもと 投稿作成者

    J君、どもです。

    ははは、これはさすがにやりすぎた感がありました。
    まぁ、ここまでで結構満足する結果が得られているので、この辺で止めときます。

    返信
  3. J君

    公儀介錯人拝一刀になってしまった師匠・・・おはようございます。(笑)

    高速化はなかなか難しいですか?
    昔なんですが、出回っているキャッシュ関連のプラグインを片っ端から試したことがあったのですが、イマイチうまく行きませんでした。
    もともとしくみをぐぐっと理解して使っているわけではなかったので、当たり前ですが・・・f(^−^;ポリポリ

    J君のほうでも利用できるプラグインができたら、是非使わせて頂きたいと思います。
    何としてもJ君も”びんさん”に勝ちたい・・・(笑)

    さて、mg12さんのレスですが、昨日師匠の書き込みの後、追跡をしていたんですが、何と日本語でレスが付いていたので
    思わずw(゜o゜)w オオー!と驚いてしまいました。師匠が英語で、レスが日本語、ちょっと不思議な感じでした。(゜o゜;)
    次回のバージョンでは、日本語言語パック付きでリリースされるということで・・・J君も嬉しいです。
    ?(^O^)/

    返信

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください