CodeIgniter の DB_Driver (save_queries) にご注意【vol.1】 の続きです。
実コードで実際のオブジェクトのダンプやメモリ使用量を比較してみたのでそのメモを。
昔に作ったローカル環境なので CodeIgniter は 2.0.3 が入っていますが、該当の部分のコードは最新でも大きく変わっていません。
実測編
使用コード
memory.php
<?php
if (!defined('BASEPATH')) {
exit('No direct script access allowed');
}
/**
* Class Memory
*
* @property Memory_model memory_model
*/
class Memory extends MY_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('memory_model');
echo memory_get_peak_usage(true) . PHP_EOL;
echo memory_get_peak_usage(false) . PHP_EOL;
}
public function index()
{
$db = $this->load->database('local', true);
$this->memory_model->getConfig($db);
}
public function index2()
{
$this->memory_model->getConfig2();
}
public function __destruct()
{
echo memory_get_peak_usage(true) . PHP_EOL;
echo memory_get_peak_usage(false) . PHP_EOL;
}
}
memory_model.php
<?php
if (!defined('BASEPATH')) {
exit('No direct script access allowed');
}
/**
* Class memory_model
*
* @property CI_Loader load
*/
class memory_model extends MY_Model
{
private $limit = 1;
private $max = 1000;
public function getConfig($db)
{
$offset = 0;
while (true) {
$db->limit($this->limit)->offset($offset)->get('hoge1_data_master_table')->result_array();
$offset += $this->limit;
if ($offset >= $this->max) {
break;
}
}
var_dump($db);
echo $db->last_query() . PHP_EOL;
}
public function getConfig2()
{
$offset = 0;
while (true) {
$db = $this->load->database('local', true);
$db->limit($this->limit)->offset($offset)->get('hoge1_data_master_table')->result_array();
$offset += $this->limit;
if ($offset >= $this->max) {
break;
}
}
var_dump($db);
echo $db->last_query() . PHP_EOL;
}
}
計測コマンド
$ time php /path/to/root/htdocs/index.php memory/index
$ time php /path/to/root/htdocs/index.php memory/index2
実行結果
途中は長いので略しています。
サマリ
単純な短いクエリですが、発行クエリと実行時間が 1,000 回記録されるので、さすがにメモリ使用量に差が出てきています。
また、毎回 DB に接続をしなおすので、オブジェクトを保持しない場合には、明らかに処理が遅くなっています。
save_queries を true にしているので last_query()
で結果を表示できています。
type | real | user | sys | peak(true) | peak(false) |
---|---|---|---|---|---|
DB オブジェクト保持型 | 0m3.821s | 0m0.698s | 0m0.162s | 8,388,608 | 8,155,616 |
DB オブジェクト非保持型 | 0m10.503s | 0m1.143s | 0m1.107s | 7,864,320 | 7,800,056 |
DB オブジェクト保持型 (index)
7602176
7508336
class CI_DB_mysqli_driver#30 (73) {
:
public $save_queries =>
bool(true)
public $queries =>
array(1000) {
:
(more elements)...
}
public $query_times =>
array(1000) {
:
(more elements)...
}
:
}
SELECT *
FROM (`hoge1_data_master_table`)
LIMIT 1 OFFSET 999
8388608
8158160
real 0m3.821s
user 0m0.698s
sys 0m0.162s
DB オブジェクト非保持型 (index2)
7602176
7508336
class CI_DB_mysqli_driver#30 (73) {
:
public $save_queries =>
bool(true)
public $queries =>
array(1) {
[0] =>
string(60) "SELECT *
FROM (`hoge1_data_master_table`)
LIMIT 1 OFFSET 999"
}
public $query_times =>
array(1) {
[0] =>
double(0.0046629905700684)
}
:
}
SELECT *
FROM (`hoge1_data_master_table`)
LIMIT 1 OFFSET 999
7864320
7800056
real 0m10.503s
user 0m1.143s
sys 0m1.107s
save_queries = false
サマリ
同じコードで save_queries
だけを false に設定したところ、メモリの使用量に差はなくなりました。この場合は、DB 接続を作り直すほうが時間だけかかるので、オブジェクトは保持したほうがよさそうです。
last_query()
の結果は表示されなくなりました。
type | real | user | sys | peak(true) | peak(false) |
---|---|---|---|---|---|
DB オブジェクト保持型 | 0m3.979s | 0m0.639s | 0m0.193s | 7,864,320 | 7,772,392 |
DB オブジェクト非保持型 | 0m9.320s | 0m1.046s | 0m1.160s | 7,864,320 | 7,799,760 |
DB オブジェクト保持型 (index)
7602176
7509808
class CI_DB_mysqli_driver#30 (73) {
:
public $save_queries =>
bool(false)
public $queries =>
array(0) {
}
public $query_times =>
array(0) {
:
}
7864320
7772392
real 0m3.979s
user 0m0.639s
sys 0m0.193s
DB オブジェクト非保持型 (index2)
7602176
7509808
class CI_DB_mysqli_driver#30 (73) {
:
public $save_queries =>
bool(false)
public $queries =>
array(0) {
}
public $query_times =>
array(0) {
}
:
}
7864320
7799760
real 0m9.320s
user 0m1.046s
sys 0m1.160s