프로그래밍/PHP

[PHP] 문자열 결합 성능 비교 (Comparison of string concatenation performance)

채윤아빠 2019. 12. 24. 11:11
728x90
반응형



PHP 코딩을 할 때, 문자열 결합(Concatenation)을 위하여 "." (dot) 연산자나, implode() 함수를 이용하게 됩니다.

문득 둘 간의 성능의 차이는 어떨지 궁금하여 다음과 같은 코드로 간단하게 성능을 비교해 보았습니다.

<?php 
/**
    performance_of_string_concatenation.php
    @brief 문자열 결합(Concatenation) 성능 비교
    @date 2019-12-24
    @author hbesthee@naver.com
    @reference https://www.sitepoint.com/high-performance-string-concatenation-in-php/
*/
header("Content-type: text/plain");

echo "CASE #1\n\n";

// array join
$str = '';
$t_implode_start1 = microtime(true);
$sArr = array();
for ($i = 300000; $i > 0; $i--) {
    $sArr[] = 'Performance of string concatenation. ';
}

$t_implode_start2 = microtime(true);
$str = implode($sArr);
$t_implode_end = microtime(true);

echo "Prepare string array : " . ($t_implode_start2 - $t_implode_start1) . " ...\n";

echo "implode() 1 : " . ($t_implode_end - $t_implode_start1) . " ...\n";
echo "implode() 2 : " . ($t_implode_end - $t_implode_start2) . " ...\n";

// standard string append
$str = '';
$t_dot_start = microtime(true);
for ($i = 300000; $i > 0; $i--) {
    $str .= 'Performance of string concatenation. ';
}
$t_dot_end = microtime(true);

echo "dot(.) operator #1 : " . ($t_dot_end - $t_dot_start) . " ...\n";

$str = '';
$t_dot_start = microtime(true);
for ($i = 0; $i < 300000; $i++) {
    $str .= $sArr[$i];
}
$t_dot_end = microtime(true);

echo "dot(.) operator #2 : " . ($t_dot_end - $t_dot_start) . " ...\n";

echo "\n\n";
echo "CASE #2\n\n";

$arrString = ['Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '
        , 'Performance of string concatenation. '];
$t_implode_start = microtime(true);
for ($i = 0; $i < 300000; $i++) {
    $str = implode($arrString);
}
$t_implode_end = microtime(true);

echo "implode() #1 : " . ($t_implode_end - $t_implode_start) . " ...\n";

$t_dot_start = microtime(true);
for ($i = 0; $i < 300000; $i++) {
    $str = 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. '
        . 'Performance of string concatenation. ';
}
$t_dot_end = microtime(true);

echo "dot(.) operator #1 : " . ($t_dot_end - $t_dot_start) . " ...\n";

$t_dot_start = microtime(true);
for ($i = 0; $i < 300000; $i++) {
    $str = "";
    for ($j = 0; $j < 11 ; $j++)
        $str .= $arrString[$j];
}
$t_dot_end = microtime(true);

echo "dot(.) operator #2 : " . ($t_dot_end - $t_dot_start) . " ...\n";
?>

위 코드를 수행한 결과는 다음과 같습니다.

CASE #1

Prepare string array : 0.067390918731689 ...
implode() 1 : 0.072884082794189 ...
implode() 2 : 0.0054931640625 ...
dot(.) operator #1 : 0.069299936294556 ...
dot(.) operator #2 : 0.063436031341553 ...

CASE #2

implode() #1 : 0.27742505073547 ...
dot(.) operator #1 : 0.05171012878418 ...
dot(.) operator #2 : 1.0956637859344 ...

"CASE #1"에서는 매우 큰 문장들 또는 배열을 하나로 합치는 예입니다.
대 부분의 시간이 배열을 생성하는데 소요됩니다. 배열이 준비되어 있다면, implode() 함수의 성능이 월등히 뛰어납니다.[2]
아무래도 "." (dot) 연산자의 경우에는 반복문으로 계속 문자열을 추가로 합치다보니, 스크립트 자체의 실행 시간까지 포함되어 한문장을 실행하는 implode() 보다는 성능이 떨어질 수 밖에 없습니다.

"CASE #2"에서는 10개 이하의 문장들 또는 배열을 하나로 합치는 예입니다.
이 경우에는 동일한 횟수의 반복문으로 스크립트가 실행되는 회수가 동일합니다.
일반 문자열을 합치는 "." (dot) 연산자의 성능이 월등히 뛰어납니다.[1] 그러나, 배열로 준비되어 있는 문장들을 반복문으로 합치려는 경우, 스크립트 자체의 실행부분 때문에 오히려 implode() 보다 성능이 떨어집니다.[2]

결론적으로 배열이 아닌 일반적인 문자열 결합에는 "." (dot) 연산자를 이용하고, DB 쿼리 결과 등과 같이 배열이 준비된 경우라면 implode() 함수를 이용하면 되겠습니다.
배열을 반복문을 통하여 "." (dot) 연산자를 이용하여 합치는 것은 코딩적으로도 낭비고, 성능도 떨어지게 됩니다.

참고자료 : High-Performance String Concatenation in PHP