お絵かき掲示板交流サイトのトップページの負荷削減

お絵かき掲示板交流サイトのトップページの新着画像の表示に使っていたスクリプト…。
foreach(glob('cgi/{foo,bar,baz}/src/{*.png,*.jpg}', GLOB_BRACE) as $filename) {
//$arr[$filename] = filemtime($filename);
$arr[$filename] = substr($filename,-17,-4);
}
unset($filename);
//連想配列を値でソート
arsort($arr);
?>
お絵かき掲示板の画像が保存されているディレクトリに入っている画像をすべて呼び出して新着画像順になるようにソート。

以前はファイルのタイムスタンプで並び替えていましたがもしひとつのディレクトリに2000枚の画像があったらディレクトリ3つで合計6000枚。

それを配列にいれるだけでなくサーバにタイムスタンプを問い合わせる処理もはいって…となるのでその処理が負荷になっていました。

それをファイル名でソートするようにすると0.09秒かかっていた処理が0.03秒に短縮。
//$arr[$filename] = filemtime($filename);
$arr[$filename] = substr($filename,-17,-4);
POTI-boardの画像ファイルのファイル名には10桁のユニックスタイムと小数点以下のマイクロタイム3桁分、合計13桁の数字が入っているのでその箇所とりだしてファイル名でソートしても同じ結果を得ることができました。

しかし、表示する画像が新着の1枚でも12枚でもglobでディレクトリ内の画像を検索して6000枚画像があったら配列の数も6000…。

あれ?ログファイルから画像のファイルのパスを取得したら?とひらめいて…。
$i=1;
$fp = fopen($val, "r");
while ($line = fgets($fp ,4096)) {
list($no,,$name,,$sub,,,
,,$ext,,,$time,,,,) = explode(",", $line);
if ($ext){
$dir=explode('/',$val);
$files[]=$no.','.$name.','.$sub.','.$dir[1].',cgi/'.$dir[1].'/src/'.$time.$ext;
// var_dump($val);
if($i>=12){break;}
++$i;
}
}
fclose($fp);
各ディレクトリの新着12枚をもとにして全ディレクトリ分の配列を作成してファイル名でソートすれば…。

12x3=36で配列の数36。

結果処理時間を0.09秒から0.006秒に短縮することができました。

従来の1/15の処理時間でほぼ同じ結果を得ることができました。
いろいろとやってみるものですね。

お絵かき掲示板交流サイトはこちら。

わかると便利なforeach

あんまりにもあんまりなコードを書いていたので、少しは進歩している事をおしらせすべく、お絵かき掲示板交流サイトのトップページで使っているphpのソースの一部を…。

<?php
$arr = array();
foreach(glob('cgi/{foo,bar,baz}/index.html', GLOB_BRACE) as $filename) {
$arr[$filename] = $filename;
}
$i = 1;
foreach($arr as $key => $value){
var_dump($key);
if($i >= 3){break;}
$i++;
}
?>

よくわからないけれど動いていたもの。

foreachは配列の数だけループするのでもし3ならbreakという処理は必要ありませんでした。

globで配列に入れる必要もありませんでした。その配列を別の配列に入れる必要もありませんでした。

<?php
$arr=array('cgi/foo/index.html','cgi/bar/index.html','cgi/baz/index.html');
for($i = 0; $i <= 2; $i++){
$filename = $arr[$i];
var_dump($filename);
}
?>

foreachがよくわからなかったので、forで記述。
しかしやや煩雑なコード…。

<?php
$arr=array('cgi/foo/index.html','cgi/bar/index.html','cgi/baz/index.html');
foreach($arr as $filename){
var_dump($filename);
}
?>

foreachが便利な事がわかったので書き直し。
配列の数だけループ。

お絵かき掲示板はこちら。

配列の最後の値を取得するコードの速度を比較

サーバの負荷が気になるので、お絵かき掲示板交流サイトのトップページのphpのコードを書き直しているところです…。

ディレクトリ内の画像から最新の画像を1枚表示したいだけなのに、ディレクトリ内に1000枚画像があったら配列の数が1000個…それをタイムスタンプで逆順でソートしてまた配列に格納…。

ファイル名の数字が同じ桁数で新しいほど数値が増えるのなら、globでディレクトリ内の画像を呼びした時点でソートがかかっているのでタイムスタンプを使った処理をしなくても…。

その処理を省略するだけで、少なくとも00.1秒は速くなるようですね。サーバの処理速度にもよりますが…。

ふと思ったのですが…。

ディレクトリに1000枚の画像が存在していたらglobで古い画像から順番に配列に格納されるので、最新の画像は1000番目になりますね…。

foreach(glob('cgi/poti/src/{*.png,*.jpg}', GLOB_BRACE) as $filename) {
}

foreachで配列の数だけループするけれど何もしない。しかしループが終わったあとに残る$filenameは配列の最後の値…。(必ずそうなる訳では無いようですが…)

$filenameに1000枚の画像のファイル名が入るので処理速度は期待できない…。

そこで…
$filename=glob("cgi/poti/src/{*.jpg,*.png}", GLOB_BRACE);
$filename=$filename[count($filename)-1];

最新の画像が表示されるので結果は同じ。ループしていないのでforeachを使うより軽い…はずだったのですがcountが重いのか…。

配列の最後の値を取得するコードの処理速度 php

$filename=glob("cgi/poti/src/{*.jpg,*.png}", GLOB_BRACE);
$filename=array_slice($filename, -1)[0];

foreach(glob('cgi/poti/src/{*.png,*.jpg}', GLOB_BRACE) as $filename) {
}

の処理速度がほぼ同じ…。

むしろforeachでループして最後に残った値を取得する下側の書き方のほうが処理時間が短くて…。

$filename=$filename[count($filename)-1];

が一番遅い…。

$filename=glob("cgi/poti/src/{*.jpg,*.png}", GLOB_BRACE);
$filename=end($filename);

配列の最後の値を取得したいのならendという関数が…と思いましたがなぜかあまり速くない。

配列の最後の値を取得するコードの処理速度 php

一番速かったのは…。一番遅いと思っていたforeachで配列を最後まで読み込んで最後に残った値…でした。

お絵かき掲示板はこちら。