1. OPCODE 란

PHP를 포함해 다양한 프로그래밍 언어로 작성된 코드는 기계어로 변환되어 실행됩니다. 이런 기계어는 명령어(operation)와 피연산자(operand)로 이루어집니다. 명령어는 프로세스 명령어 집합으로 사전에 정의되어 있는데, 각 명령어를 지정하는 연산 코드(operation code)로 표시됩니다. 연산 코드를 줄여서 ‘opcode’라고도 부릅니다. 피연산자는 명령어가 처리할 메모리 주소 값 또는 데이터 값을 말합니다.

2. OPCODE 캐시란

PHP는 인터프리터 언어의 특성 때문에 실행 될 때마다 opcode로 파싱 변환되어 실행이 됩니다. opcode 캐시는 한번 생성된 opcode를 공유 메모리에 캐시 형태로 저장하여, 다음에 동일한 컴파일 작업을 반복하지 않고 바로 실행되도록 합니다. 다시 말해 opcode 캐시를 이용하면 PHP 스크립트 파일을 디스크에서 읽은 뒤에 컴파일 하는 과정이 생략되므로 프로그램의 실행 속도를 개선할 수 있게 됩니다.

출처: 참고 문헌 [1] opcode cache (PHP 캐시) 웹서버

3. OPCODE 캐시의 작동 프로세스

opcode 캐시의 작동 프로세스를 이해하려면 PHP 코드를 기계어로 변환하는 과정부터 이해할 필요가 있습니다. 먼저 Zend 엔진 파서(parser)가 PHP 코드를 opcode로 변환하고, 이후 실행기(executor)는 전달받은 opcode를 해석하여 실행합니다.

opcode 캐시는 프로그램 성능을 개선하기 위해 위 프로세스를 다르게 처리합니다. Zend 엔진이 스크립트 파일의 로드를 요청하면 스크립트의 이름이 opcode 캐시에 전달되고 opcode 캐시는 stat() 시스템 호출을 통해 해당 파일의 정보를 확인합니다. 컴퓨터 운영체제는 하나의 파일에 대해 하나의 inode를 생성하는데, 이를 통해 각 파일을 유니크하게 식별할 수 있습니다.

이후 opcode 캐시는 해시 테이블(hash table)을 조회하여 해당 파일이 이전에 처리된 일이 있는지 조사하여 파일의 수정 시간을 해시 테이블에 저장된 정보와 비교합니다. 이전에 처리된 일이 없거나 파일의 수정 시간이 다른 경우, 파서가 호출되어 해당 파일에 대한 opcode가 생성되고, inode, 변경 시간 등의 정보와 함께 캐시에 저장됩니다. 그리고 생성된 opcode는 실행기에 전달됩니다.

PHP에서 opcode 캐시가 동작하는 과정은 아래 그림과 같습니다.

출처: 참고 문헌 [2] PHP Performance I: Everything You Need to Know About OpCode Caches

4. OPCODE 캐시 사용의 이점

opcode 캐시를 이용하면 반복적인 파싱 작업에 수반되는 오버헤드를 줄이고, 최적화된 opcode 집합을 활용함으로써 코드 실행 속도를 개선할 수 있습니다. 디스크에서 파일을 읽어 들일 필요가 없으므로 파일 I/O도 줄어 듭니다.

PHP의 기본 설정에서는 Zend 컴파일러는 스크립트를 opcode로 변환하는 작업을 최대한 신속하게 완료하기 위해 최적화된 opcode 집합을 생성하지 않습니다. 컴파일러가 모든 명령어를 일일이 최적화해야 한다면 실행 속도가 조금 빨라지는 대신 파싱에 소요되는 시간이 증가되기 때문입니다. 하지만, opcode 캐시가 사용되는 환경에서는, opcode가 최초로 사용되는 시점에 조금 더 많은 시간을 투자하여 최적화 작업을 마무리함으로써 이후 반복 수행되는 작업 시간을 단축하는 것이 가능합니다.

opcode 캐시를 사용하기 위해 기존에 작성된 코드를 변경할 필요는 전혀 없습니다. php.ini에서 opcode 캐시의 활성화 여부만 변경하면 되므로 구현 또한 쉽습니다. 단, PHP 5.5 미만 버전에서는 모듈 설치가 별도로 필요합니다.

5. OPCODE 캐시 모듈

opcode 캐시를 지원하는 모듈은다음과 같습니다.

  • Zend Opcache
    • PHP 5.5 버전부터 제공되는 모듈로 설정만 변경하면 사용할 수 있습니다.
  • APC(Alternative PHP Cache)
    • PHP 개발자 그룹에서 만든 캐시 모듈이며, PHP 5.5 버전부터 Zend Opcache가 번들되면서 현재는 개발이 중단되었습니다. APC의 opcode 캐시 기능을 삭제하고 데이터 스토어 기능만 지원하는 APCu가 개발되었습니다.
  • Xcache
    • lighttpd를 만든 lighty 팀에서 lighttpd와 같이 사용할 목적으로 개발된 PHP 엑셀레이터입니다. opcache 캐시 외에 객체 캐시 기능을 제공합니다.

6. OPCODE 캐시 벤치마크

PHP에서 opcode 캐시 사용에 대한 벤치마크에 대한 결과는 인터넷에서 검색할 수 있었습니다. 그 한 사례는 다음과 같습니다.

출처: 참고 문헌 [6] Minimum front page load times for common applications

위 벤치마크의 테스트 환경은 다음과 같습니다.

  • Host: Intel i7-3770, 32GB RAM, SATA disks
  • OS: single LXC container (Slackware in Slackware, custom built)
  • Apache HTTPD 2.4.16, PHP runs as embedded module
  • HTTP request logging was enabled, as it seems it does not influence results noticeably
  • MySQL 5.6.25, default table engine InnoDB
  • ApacheBench command: ab -k -c1 -n100

저자는 아래와 같은 환경에서 직접 벤치마크 테스트를 수행하였습니다.

  • Host: AWS EC2 Dokyo Instance
  • OS: Ubuntu 12.04.2 LTS
  • Nginx 1.4.4, PHP-FPM 5.5.6, Redis 2.6.16, 8vCore , 8GB RAM
  • MariaDB 5.5.32 with connection pooling, 8vCore , 16GB RAM
  • ApacheBench command: ab -t 30 -c 100

테스트 유형은 MariaDB 읽기/쓰기, Redis 읽기/쓰기, 텍스트 출력(Echo), 암호화(Encryption) 4종을 각각 수행했습니다. 그 결과는 아래와 같습니다.

  • TPS(Transaction Per Second): 초당 처리 건수
  • LOAD: 시스템 부하, 1개 코어에 1 단위가 시스템에서 처리할 수 있는 적정 부하, 현재 시스템은 최대 8

opcode 캐시가 적용되면 시스템의 부하가 감소하고 더 많은 트랜젝션을 처리할 수 있는 것을 알 수 있습니다. 더불어 CodeIgniter 프레임워크를 사용하면 개발 생산성을 증진시키고, 협업 및 유지보수를 수월하게 할 수 있는 장점이 있지만 시스템 부하는 상당히 커지는 것은 어쩔 수 없습니다. 하지만, CodeIgniter 프레임워크를 사용하는 경우에 opcode 캐시를 이용하면 더 큰 효과를 발휘하여 약 4배의 트랜젝션을 처리할 수 있는 것을 확인할 수 있습니다.

참고 문헌

[1] opcode cache (PHP 캐시) 웹서버 https://blog.naver.com/junix/80099814805
[2] PHP Performance I: Everything You Need to Know About OpCode Caches https://support.cloud.engineyard.com/hc/en-us/articles/205411888-PHP-Performance-I-Everything-You-Need-to-Know-About-OpCode-Caches
[3] PHP 시리즈를 배포, 제 3 부 : 오라클 PHP 코드의 실행 속도를 가속 http://www.oracle.com/technetwork/cn/articles/alshanetsky-deployphp-092550-zhs.html
[4] Zend OPcache 설치 및 설정 https://www.lesstif.com/pages/viewpage.action?pageId=23757119
[5] PHP 가속기 https://www.solanara.net/solanara/php#head_php_accel
[6] Minimum front page load times for common applications https://blog.a2o.si/2015/09/06/php-5-6-vs-php-7-0-vs-opcode-cache-common-application-performance-benchmark/
[7] FastCGI with a PHP opcode cache benchmarks https://blog.naver.com/parkjy76/30147938375
[8] PHP 5.5: Zend Optimiser+ OPcache vs XCache http://massivescale.blogspot.kr/2013/06/php-55-zend-optimiser-opcache-vs-xcache.html

백종만

2012년부터 회사에 입사하여 게임개발 플랫폼 개발등 다양한 일을 하고 있습니다. 최근에는 팀에서 iOS개발과 함께 배포 프로세스 자동화, 개발환경 개선등의 업무를 진행하고 있습니다. 시간이 걸리더라도 실수를 줄일 수 있는 코드를 작성하는 것을 목표로 노력하고 있습니다.


TOP