최근 json 파일을 읽어와 데이터 처리를 하면서 궁금증이 생겼다.
파일읽기 함수는 여러가지가 있는데 이중 속도차이가 많이 날까라는 의문이였다.
나같은 경우 파일 내용을 읽을 시 file_get_contents 와 include 를 많이 사용했는데 검색하다보니
file_get_contents 가 더 빠르다는 글이 있어 몇가지 함수를 더 추가해서 테스트를 해보았다.
테스트의 경우 아래의 함수를 기준으로 하였다.
|
위의 함수중 file 함수같은 경우 line 단위로 읽어와서 배열에 담기 때문에 막상 출력할려면 상당히 느리고
파일읽기 성능 테스트와는 그렇게 맞지 않긴 하지만 그래도 한번 넣어보았다.
처음 테스트 결과는 이렇다.
1위: include, 0.000071초 걸림
|
역시나 include 가 빠르긴 했으나 맨 처음 실행했을때는 그렇게 성능이 좋지만은 않았다.
그렇게 테스트를 몇번 더 해보고 난뒤 아무래도 file_get_contents 속도가 빠른 경우가 있지 않을까 하여
여러 방법으로 테스트를 해보았고 그 경우의 수를 찾게 되었다.
그건 바로 읽을 데이터 파일의 크기였다.
처음 테스트했던 데이터의 경우 5천줄이 넘지 않는 데이터였는데, 그 후 10만줄이 넘는 데이터로
테스트를 해보니 확실 히 차이가 보이기 시작했다.
10만줄로 테스트한 결과는 아래와 같았다.
1위: file_get_contents, 0.024729초 걸림
|
include 가 1위에서 3위로 밀린것을 확인가능한데 사실상 캐싱 되기전에는 5위였다.
결론적으로는 파일 내용을 읽을때는 file_get_contents 를 사용하는게 좋다.
include 같은 경우 아무래도 PHP 소스 내용이 있을 경우 조건처리가 되기때문에
파일 내용 읽기로는 맞지 않다.
그동안은 아무생각없이 include 로 ob_start 함수와 조합해서 파일을 막 읽어 들였는데 내용만 읽을 때는
include 는 절대 사용하면 안되겠다는 생각을 가지게 되었다.
아래는 이번에 테스트하면서 만든 소스인데 결과가 궁금한 경우 아래 소스를 가지고
직접 테스트 해보길 바란다.
<?php
function get_time() { $t=explode(' ',microtime()); return (float)$t[0]+(float)$t[1]; }
function get_exec($filename , $type, $count = 10){
$start = get_time();
for($i=0;$i<$count;$i++){
$contents = '';
switch($type){
case "fgets":
$handle = fopen($filename, "r");
while (($buffer = fgets($handle, 4096)) !== false) { $contents .= $buffer;}
fclose($handle);
break;
case "fread":
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
break;
case "file":
$handle = file($filename);
foreach($handle as $v){ $contents .= $v; }
break;
case "file_get_contents":
$contents = file_get_contents($filename);
break;
case "include":
ob_start();
include $filename;
$contents = ob_get_clean();
break;
}
}
$end = get_time();
$time = $end - $start;
return $time;
}
$test = array('fgets','fread','file','file_get_contents','include'); // 테스트 정의
$result = array(); // 결과
$filename = dirname(__FILE__)."/test.txt"; // 읽을 파일
$count = 1; // 실행 횟수
foreach($test as $k=>$v){
$time = get_exec($filename,$v,$count);
$result[$v] = $time;
unset($time);
}
asort($result);
$rank = 1; // 랭킹 표시용도
foreach($result as $k=>$v){
echo ($rank++).'위: '.$k.', '.number_format($v,6).'초 걸림';
echo '<hr>';
}
echo '총 걸린시간: '.number_format(array_sum($result),6);