티스토리 뷰

예전에 nzeo.com (제로보드사이트)의 웹스터디 PHP 게시판에 올렸던 글과 코멘트에 덧붙였던 내용을 같이 잘 조합해서 올려봅니다..; 아시는 내용이라면 모르시는 분들을 위해서 패스~ 수정 사항이나 추가 사항있으면 코멘트 때려주세요;;
------------------------------------------------------------------------------------------------------------------------


웹사이트 성능에 큰 영향을 주는 부분은 대개 부적절한 혹은 최적화되지 않은 데이터베이스 쿼리문에 있습니다.
하지만 데이터베이스 쿼리문이 최적화되었더라도 PHP 프로그램내에서의 간단한 몇가지 수정으로도 좀더 성능 개선을 할 수 있습니다.
해외 PHP관련 컨퍼런스등에서 여러번 제시된적 있는 몇가지 성능 튜닝을 위한 유용한 팁을 올립니다.



 1. 최대한 쌍따옴표 대신에 일반따옴표를 쓴다.

쌍따옴표로 감산 문자열의 경우 PHP는 문자열 전체를 처리하게 됩니다.
따라서 처리되지 않고 그대로 유지될 혹은 나중에 처리되어야할 문자열의 경우 일반따옴표를 쓰는 것이 좋습니다.

예) $string = '문자열';

문자열 중간에 변수가 삽입될 경우에도 최대한 일반 따옴표를 쓰는 것이 좋지요.

예) $string = '문자열1' . $string2 . '문자열2';

참고로 성능튜닝은 아니고 코딩스타일인데, 쌍따옴표로 감싼 변수가 삽입된 문자열의 경우 변수는 { 와 }로 감싸주는 것이 좋습니다.
이 경우 객체변수나 배열변수 혹은 배열+객체변수도 삽입 가능합니다.

예) $string = "문자열1 {$string2} 문자열2 {$object->var} 문자열3 {$array[0]} {$array[1]->var}";

주의할 점)
아시겠지만 문자열에 일반따옴표가 들어갈 경우 따옴표마다 앞에 역슬래쉬로 escape시켜줘야 하는 점입니다.
쌍따옴표는 그대로 표현하면 됩니다.
이런 문자열변수를 eval로 처리할 경우에는 미리 str_replace() 함수로 쌍따옴표 앞에 역슬래쉬를 붙여주는 작업이 필요하게 됩니다.
이러한 점만 숙지한다면 큰 문제는 없을 것입니다.



 2. 루프문에서 함수 사용은 금물

for ($i=0; $i<count($array); $i++) {

위와 같은 for 루프문들이 쓰이는 것을 곧잘 볼 수 있습니다.
PHP의 for 루프문, 두번째 인자의 함수는 매 루프마다 불려지기 때문에
배열이 클수록 함수를 부르는데 걸리는 시간만으로도 실행 시간을 상당히 뺏기게 됩니다.
이는 다음과 같이 바꿔주는 것이 좋습니다.

예1) for ($i=0, $cnt=count($array); $i<$cnt; $i++) {

예2)
$cnt = count($array);
for ($i=0; $i<$cnt; $i++) {

이 방법만으로도 엄청난 성능 개선을 가져왔다는 예도 있습니다. 배열이 무척 컸나보네요^^;
추가: 실제로 저의 경우에도, 엄청나지는 않았지만 꽤 괜찮은 성능개선을 맛봤었답니다 :)



 3. 버퍼링

기본적으로 PHP의 버퍼 크기가 8K이기때문에 결과물이 크면 나누어서 보내야 하기에 I/O 시간만으로도 상당한 시간을 잡아먹게 됩니다.
하지만 버퍼링으로 결과물을 모았다가 한꺼번에 뿌려주게 되면 다른 방법들을 쓰지 않더라도 몇배의 성능 개선도 가져올 수 있습니다.

간단히 스크립 처음에 마지막에 각각 ob_start() 와 ob_end_flush() 를 추가해주기만 하면 됩니다.

그냥 ob_start() 대신 ob_start('ob_gzhandler') 로 추가할 경우 (PHP에 gzip 모듈이 올라와 있어야 합니다.)
대부분의 웹브라우져가 압축을 지원하므로 트래픽양을 줄일 수 있고 결과적으로 클라이언트의 화면에 페이지가 뜨는데 걸리는 시간이 단축됩니다.
이 방법을 쓰더라도 웹브라우져가 압축을 지원하지 않으면 압축을 하지 않고 보내므로 따로 압축을 지원하는지 안하는지 확인할 필요도 없습니다.



 4. 옵코드 캐싱

PHP의 젠드엔진은 PHP코드를 자체적인 옵코드로 컴파일한 후 실행을 합니다.
이 부분에서도 로드가 높은 사이트에서는 상당한 오버헤드가 일어날 수 있습니다.
따라서 PHP코드를 새로 컴파일해서 실행하는 것보다는 기존에 컴파일된 옵코드를 바로 실행하면 많은 실행속도를 단축시킬 수 있습니다.
이는 옵코드 캐시 모듈을 적재해야 하기 때문에 모든 곳에서 적용하기는 힘들 것입니다.
하지만 제가 알기론 대부분의 호스팅회사에서는 젠드옵티마이저를 적재하기 때문에 따로 신경쓰지 않으셔도 될것입니다.
만약 서버관리권한이 있거나 한다면 다른 옵코드 캐싱 모듈을 써보실 것도 권해드립니다.
APC(Advanced PHP Cache), Eaccelerator 혹은 현재는 개발 중단된 Turk-MMCache 등이 있는데, APC는 PECL로 설치가 가능하며 상당히 좋습니다.
Eaccelerator가 성능은 좀더 낫다는 것 같지만요. 이는 직접 테스트 비교해보는 것이 좋을 것입니다.
주의할 점은 젠드옵티마이저를 사용하지 않으면 젠드컴파일러로 컴파일된 바이너리는 실행하지 못한다는 단점이 있습니다.
컴파일된 상용 php프로그램 사용시에는 다른 방법이 없습니다..^^;;; 

 

 5. Regular Expression : POSIX Extented(ereg_) VS. Perl-Compatible(preg_)

대부분의 속도비교결과 Perl-Compatible 정규표현식이 조금 더 빠르다고 합니다. perl호환 정규표현식을 사용하기를 권장합니다.



 6. 정규표현식 VS. str_replace()

간단한 문자 치환의 경우에는 str_replace() 함수를 쓰는 것이 훨씬 빠릅니다.
복잡한 따라서 정규표현식을 꼭 써야하는 경우를 제외하고는 PHP 기본문자함수를 쓰는 것이 좋습니다.



 7. is_numeric(), is_integer()등 VS ctype_XXX()

변수의 형식을 체크할 시 기본 PHP함수보다 ctype이 더 빠르다고 합니다.
대신 ctype으로는 11가지 형식에대한 체크만 가능하다는 한계가 있으므로 자세한 것은 PHP매뉴얼을 참조하시길 바랍니다.
ctype은 PHP 매뉴얼에서 Character Type Functions 항목입니다.
  License
본 게시물은 GFDL을 따릅니다. [ GFDL 안내 ]

코멘트 리스트 -->
   너만사랑해   06-10-04 19:13  
좋은 정보 ㄳ~~
   t3RRa   06-10-04 19:21  
쓰고보니 생각나서...
위에서 옵코드 캐쉬에 관련된 내용에서 젠드옵티마이저가 아니라 젠드액셀러레이터입니다.
이건 상용이라서 어짜피 일반 호스팅업체에선 잘 설치가 안되어 있을겁니다;;
그런데 APC가 PHP6에서는 기본 모듈로 채택될 예정이고
PHP 창시자가 APC 프로젝트에 참여하고 있죠.. 아마도 APC로 가는 것이 좋을겁니다... :)
   공대여자   06-10-04 19:39  
6번만 잘 구문해도 엄청나죠.
str_replace()로 하면 끝나는데 정규식 쓰는건... 도시락 싸고서 말리고 싶습니다.
   낭망백수   06-10-04 21:28  
ob .. 즐겨쓰고는 있었는데, 성능이 더 좋다고 생각해본 적은 없었습니다. 다행이네요. ^^;;;

2번에 대한 테스트 코드를 예의 코드 그대로 사용해도 됩니까? 혹시 성능데이터가 따로 있는지요?

6번. 동일한 이유로...
문자열분리에 split 보다는 explode 를 사용하는 것이 빠릅니다.

꾸벅~!
     
   t3RRa   06-10-05 05:14  
output buffer의 경우, 특히 파일을 여러개 인클루드했을때 빛을 발하는것 같습니다.
제 개인적인 경험에서 말씀드리는거라서 다른곳에선 어떨지는 모르겠습니다;;
내부서버에서 개발시 이상이 없었던 사이트가
직접 서비스를 위한 가상서버 계정에 올리니 많이 느려서
본문에서 언급한 여러가지 튜닝을 해보면서 확인했습니다.
파일 인클루드 줄이고 ob 쓰고 하니까 현저히 좋아지더군요.
지금은 독립서버에서 운영중이라서 그런 문제는 없습니다만 ^^;

2번에 대해서 예의 코드를 그대로 사용하시면 됩니다. 다른 더 좋은 방법이 있다면 알려주시고요.
제게 성능 데이터는 없습니다. 이에 관해서는 해외 사이트 이곳저곳에 올라와 있습니다.
제가 읽은 PHP 컨퍼런스 프레즌테이션들과 몇 토론에서 이에 대해 나와 있었습니다.
C에서는 최적화를 통해 매번 실행하지 않지만 PHP에서는 루프 반복시마다 실행한다고 합니다.
제가 읽은바로는 누군가 직접 PHP소스코드를 읽어보고 한 얘기였던걸로 기억합니다.
이부분에 대해서도 제가 위에 언급한 사이트에 적용하였고 그리 데이터가 많은 상태도 아니였지만,
xdebug로 살펴본바 코드 실행시간에서 약간의, 하지만 눈에 띄는 향상이 있었습니다.
즉 xdebug 결과에서 count() 가 수백번 실행된 부분이 여러개 있었는데,
그 부분들이 없어지니 그만큼 실행시간이 단축되더군요.
이 부분에 대한 링크 찾으면 걸어드리겠습니다 :)
     
   t3RRa   06-10-05 05:24  
지금 찾을수 있는건 다음 두 링크입니다. 제가 읽었던 글들은 아니지만. 테스트결과도 나오네요..;;

http://hudzilla.org/phpbook/read.php/18_1_7

http://72.14.235.104/search?q=cache:QzguMgptPs0J:linuxalpha1.eicn.ch/OReilly_books/books/webprog/php/ch13_05.htm+php+performance+tuning+for+count()+execute&hl=en&ct=clnk&cd=9
   개놈프로젝트   06-10-04 21:50  
ob_end_flush();  ^^;
     
   t3RRa   06-10-05 04:59  
앗 이런;; 그것도 다시 한번 안보고 적었네요.
항상 헷갈리는게 end와 flush의 순서--;;;
지적 감사합니다! 수정했습니다 ^^
     
   엘리   06-10-08 20:31  
ob_end_flush()  안해줘도 문서 끝나면 자동으로 처리되는 것으로 알고 있습니다.
          
   t3RRa   06-10-08 23:05  
네. PHP 매뉴얼 문서에 보면 자동으로 처리된다고 나옵니다만,
알고는 있지만, 안쓰면 왠지 코드가 완성되지 않은 느낌이;;;
   빛짱2   06-10-04 23:44  
감사합니다.  간단한 몇가지 부터 실천으로 옮겨야겠습니다.
   sjsjin   06-10-05 12:17  
잊을만 하면 꼭 한 번씩 올라오는 군요..
수도 없이 토론했는데..
     
   t3RRa   06-10-06 18:18  
어디에 올라와있고 어디서 토론을 하셨는지요?
팁앤텍에 '성능'이란 단어로 검색해서 다 찾아봐도 같은 내용은 없어서요.
제가 생각나는대로 정리해서 nzeo.com에 예전에 (꽤 되었습니다) 올렸었던것을,
다른 게시판에 따옴표 관련 내용이 있는 글이 있어서 한번 올려본 것입니다.
서론에서도 언급했듯이 혹시 모르는 분이 계실까 올린거구요.^^;
   과일™   06-10-06 21:52  
위 내용에 대해서는 언급된 적이 많긴 했었지만..
이렇게 한꺼번에 정리까지 잘해서 올라온 경우는 처음이네요. ^^
7번은 이번에 저도 처음 알게 되었네요.
좋은 정보 감사드립니다. :)
   엠돌이   06-10-08 23:25  
좋은 정보 감사합니다.
   Chan   06-10-09 00:48  
이쪽 계열은 아니지만. 감솨~
   하랑이짱   06-10-09 14:30  
좋은정보 ㄳ
   하늘사랑   06-10-09 15:39  
좋은 글입니다.. 많이 참고 되었습니다.
   내가니냐   06-10-09 18:27  
몰랐던게 몇개 있네요~~ 감사히 봤습니다~~~^_^
   맨발   06-10-09 21:57  
Character Type Functions 은 첨보네요.
감사히 봤습니다. ^^*
   혼수상태   06-10-10 12:58  
3번 무지 무지 감사합니다.
   VBer   06-10-10 15:40  
이 글을 보고서야 알게 된 정보가 많네요... ^^
   Gui   06-10-10 16:18  
^^ 좋은 정보 감사합니다.
   MuMbi준환   06-10-15 18:02  
ob_start 가 버퍼링하는건 알았는데 버퍼링이 성능에 영향을 주는지는 몰랐네요.

head sent 에러날 때 ob_start 거거
     
   t3RRa   06-10-17 09:46  
버퍼링이란게 모았다가 한번에 뿌려주는거죠.
html을 뿌려주는데 한줄 한줄 echo 로 뿌려주는 것보다 변수에 담아서 아니면 직접 echo 한번으로 뿌려주는게 더 빠른 것과 같습니다. (특별한 경우가 아니라며 이는 사람이 감지할만한 차이는 아니지요)
또한 그림을 화면에 뿌려줄때 일일이 점을 찍어주는 것보다 화면에 대응하게 그림데이터를 메모리에 뿌려주고 그 메모리를 비디오메모리쪽으로 한꺼번에 복사해서 출력되게 하는게 훨씬 빠른 것과 같은 이치라고 보면 되겠지요.
   t3RRa   06-10-19 09:11  
아파치와 PHP에도 버퍼링 설정이 있어서 이들 설정도 알맞게 튜닝해주면 더욱 좋습니다 -_-b
   영짱   06-10-31 12:28  
도움이 되었습니다. 감사^-^
   프라핏75   06-11-02 18:27  
http://teeroz.egloos.com/2703307

위 글을 보고 몇가지 테스트를 해보았습니다.
1. 문자열에서 큰따옴표나 작은따옴표는 성능은 똑같다. 그러나, 큰따옴표를 사용하여 변수를 삽입하는 경우에 큰 속도차가 나게 된다.
2. 레퍼런스 파라미터는 사용하지 않는 것이 좋다.
3. 비교문에서는 "===" 가능한한 연산자를 사용해라.
4. switch 와 if 문 중에서는 if 문이 속도면에서는 더 나을 수(!) 있다.

'프로그래밍 > PHP' 카테고리의 다른 글

메일 대용량 발송 관련 참조  (2) 2008.06.22
php 템플릿 powered by Smarty  (0) 2008.06.22
php 기본참고사항  (0) 2008.06.22
php이용 PDF 만들기에 대한 생각  (0) 2008.06.22
이미지 워터마크 구현 함수  (0) 2008.06.22
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크