삽질하는플머

PHP 컴파일러 HipHop for PHP from facebook

이런저런잡다구리/LinuxHeaven
PHP코드를 C++코드로 변환, g++로 빌드할 수 있게 하는 물건. 
결과물로 libevent 를 사용한 독립 웹서버 실행파일이 떨어진다. 
페이스북에서 쓰이고 있으며 성능 개선이 상당하다고 한다. 
모든 PHP 코드가 다 동작하는 것은 아니겠지만 관심이 무럭무럭!!

일단 홈페이지. 
https://github.com/facebook/hiphop-php/wiki/

한글로 된 소개글
http://enzine.tistory.com/entry/HipHop-for-PHP-%EB%8D%94-%EB%B9%A0%EB%A5%B8-PHP%EB%A5%BC-%EC%9C%84%ED%95%B4

KLDP의 새소식
http://kldp.org/node/112325

먼저 써보신 분의 의견. 
http://code.p-ark.co.kr/167 





레드마인을 위해 설치해 둔 우분투 10.04에 깔아보자. 9.10에 설치하는 참고링크는 여기.
https://github.com/facebook/hiphop-php/wiki/Building-and-Installing-on-Ubuntu-9.10
10.10용은 여기. (명색이 LTS인 10.04만 빠져있네...) 
https://github.com/facebook/hiphop-php/wiki/Building-and-Installing-on-Ubuntu-10.10


먼저 관련프로그램 설치. 

sudo apt-get install git-core cmake g++ libboost-dev libmysqlclient-dev libxml2-dev libmcrypt-dev libicu-dev openssl binutils-dev libcap-dev libgd2-xpm-dev zlib1g-dev libtbb-dev libonig-dev libpcre3-dev autoconf libtool libcurl4-openssl-dev libboost-system-dev libboost-program-options-dev libboost-filesystem-dev wget memcached libreadline-dev libncurses-dev libbz2-dev libc-client2007e-dev



9.10과 마찬가지로 10.04의 libmemcached 는 버전이 0.31이므로 쓸 수 없다. 0.39 이상이 필요하므로 따로 빌드. 

HipHop 소스 얻기. 

mkdir hiphop
cd hiphop
git clone git://github.com/facebook/hiphop-php.git
cd hiphop-php
export CMAKE_PREFIX_PATH=`/bin/pwd`/../
export HPHP_HOME=`/bin/pwd`
export HPHP_LIB=`/bin/pwd`/bin
git submodule init
git submodule update
cd ..



LIBEVENT 빌드.

wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz
tar -xzvf libevent-1.4.13-stable.tar.gz
cd libevent-1.4.13-stable
cp ../hiphop-php/src/third_party/libevent-1.4.13.fb-changes.diff .
patch -p1 < libevent-1.4.13.fb-changes.diff
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ..



ICU4 빌드

wget http://download.icu-project.org/files/icu4c/4.2.1/icu4c-4_2_1-src.tgz
tar -xvzf icu4c-4_2_1-src.tgz
cd icu/source
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ../../




LIBCURL 빌드. 시스템 시간 잘 맞추지 않으면 ./configure 가 실패한다네. 
중간에 패치가 필요하므로 지정된 버전을 쓸 것. 

wget http://curl.haxx.se/download/curl-7.20.0.tar.gz
tar -xvzf curl-7.20.0.tar.gz
cd curl-7.20.0
cp ../hiphop-php/src/third_party/libcurl.fb-changes.diff .
patch -p1 < libcurl.fb-changes.diff
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ..



LIBMEMCACHED 빌드. 현재 최신버전인 0.49로

wget http://launchpad.net/libmemcached/1.0/0.49/+download/libmemcached-0.49.tar.gz
tar -zxvf libmemcached-0.49.tar.gz
cd libmemcached-0.49
./configure --prefix=$CMAKE_PREFIX_PATH
make
make install
cd ..



HipHop 빌드. 걸어놓고 밥먹고 오자. 

cd hiphop-php
cmake . <- 점 주의!
make



hphp 바이너리가 src/hphp 에 생성된다. 

  



테스트. 사용법은 일단 여기.
https://github.com/facebook/hiphop-php/wiki/Running-HipHop


먼저 hphp를 체크아웃 한 디렉토리로 이동. (내 경우 ~/hiphop/hiphop-php)

export HPHP_HOME=`pwd`
export HPHP_LIB=`pwd`/bin



우분투에서는 추가로 이렇게 해주라는군.

export CMAKE_PREFIX_PATH=`/bin/pwd`/../



예전 GD 가지고 놀 때 코드를 한번 컴파일 해보자. 
적당한 디렉토리에 예제 php 파일 생성. 


ip-test.php
  

<?php
$img_number = imagecreate(140,25);
$backcolor = imagecolorallocate($img_number,255,255,255);
$textcolor = imagecolorallocate($img_number,50,104,28);

imagefill($img_number,0,0,$backcolor);
$number = "IP - $_SERVER[REMOTE_ADDR]";

Imagestring($img_number,3,0,5,$number,$textcolor);

header("Content-type: image/jpeg");
imagejpeg($img_number);
?>



컴파일

$HPHP_HOME/src/hphp/hphp ip-test.php -k 1 --log=3 --force=1 




임시 디렉토리 (내 경우에는 /tmp/hphp_TFludl) 에 실행파일이 생성된다. 
8080포트에서 구동시키는 예. 80포트로 띄우려면 관리자권한(sudo)이 필요하다. 

/tmp/hphp_TFludl/program -m server -p 8080


 
해당 서버에 접속해보자. http://my-ubuntu:8080/ip-test.php
결과는 짜잔~~





GD 테스트를 조금 더 해본다. 
프리타입이 동작하는지도 확인해보자. 윈도의 gulim.ttc 를 /tmp 에 복사해넣자. 

gd-test.php

<?php
// 이미지 생성
$image_test = ImageCreate(200,150);

// 색의 설정
$grey = ImageColorAllocate($image_test,200,200,200);
$blue = ImageColorAllocate($image_test,0,0,255);

imagefill($image_test,10,0,$grey);

// 내장폰트 사용 예
Imagestring($image_test,3, 25,50,"hahaha",$blue);

// 프리타입으로 TTF 폰트 사용 예
Imagefttext($image_test,10, 0, 25, 100, $blue, "/tmp/gulim.ttc", "우하히");

header("Content-type: image/png");
imagepng($image_test);
ImageDestroy($image_test);
?>



HipHop은 컴파일 이전에 이 PHP가 제대로 동작할지를 미리 확인해볼 수 있는 hphpi 를 제공한다. 

$HPHP_HOME/src/hphpi/hphpi  -m server -p 8080



현재 디렉토리를 기준으로 서버가 동작한다. 매번 빌드하는 것도 시간이 걸리는 일이므로, 이걸 쓰면 지금 작성중인 코드가 HipHop에서 잘 동작하는지 확인해 볼 수 있다. 

접속해보면 잘 처리되는데... 



이 PHP 파일에 include, 또는 include_once 를 써서 다른 PHP 유니트를 포함시키면 이미지 출력이 제대로 되지 않는다. 
이미지 출력을 위해 사용되는 header(), imagepng() 등의 함수가 아예 동작하지 않는 듯 하다. 
현 시점에서 GD 관련해서는 단일 유니트만 사용 가능할 듯. 진심으로 아쉬운 부분... 




예전 게임서버는 DB 입출력을 담당하는 에이전트 서버를 통해 각종 정보를 저장해 왔었다. 
이 경우 운영도 귀찮고 뭐 하나 바꾸려 할때 만져야 할 부분이 참 많다. 

때문에 로그 저장 서버는 상대적으로 편한 PHP + xmlrpc 를 써서 만들었었고
나중에 게임서버를 새로 만든다면 DB 입출력은 이 방식으로 하리라 마음먹었었는데...

HipHop을 이용하면 그 부분도 네이티브 바이너리로 굴릴 수 있다는 이야기. 
퍼블리셔에 텍스트로 된 PHP 파일을 그대로 전달해야 하는 찝찝함도 더불어 해결. 

다만 생성된 실행파일의 크기가 약 20메가 정도로 큰 편인데, UPX로 압축하면 7메가 정도로 줄어든다. 

# sudo apt-get install upx-ucl
# upx program


서버에서 실행파일의 크기야 별 의미가 없겠지만... 

언제 시간날 때 VCL4PHP 를 빌드해봐야겠다. 
 



 
2011.8.6. XMLRPC 를 HipHop for PHP로 구동시켜보자. 
 
디렉토리 구성은 다음과 같이.


루트
test.php : 에코함수인 EchoFunc() 가 구현된 서버.
  • lib : php-xmlrpc 의 lib

먼저 제대로 동작하는지 테스트 해보자. 
 

$HPHP_HOME/src/hphpi/hphpi -m server -p 8080


 
접속해보면 자알~~ 동작한다.
이제 빌드해보자.

먼저 웹루트에서 다음과같이 파일목록을 만든다.

find . -name "*.php" > files.list



files.list 의 내용은 다음과 같다. 

./test.php
./lib/compat/var_export.php
./lib/compat/is_scalar.php
./lib/compat/is_callable.php
./lib/compat/is_a.php
./lib/compat/array_key_exists.php
./lib/compat/version_compare.php



test.php 의 내용은 다음과 같다. 

<?php

include("lib/xmlrpc.inc");
include("lib/xmlrpcs.inc");

$xmlrpc_internalencoding="UTF-8";

/****************************************************************
 테스트. 에코함수.
****************************************************************/

$EchoFunc_sig = array(array($xmlrpcString, $xmlrpcString));
$EchoFunc_doc = "에코함수!!";

function EchoFunc($m) {
        // 전달된 XML에서 인자값을 뽑아낸다.
        $s=$m->getParam(0);
        $msg = $s->scalarval();
        return new xmlrpcresp(new xmlrpcval("니가 웹서버에 보낸 메시지: " . $msg, "string"));
}

/****************************************************************
 서버 구동
****************************************************************/
$s = new xmlrpc_server(array(

        "EchoFunc" => array(
                "function" => "EchoFunc",
                "signature" => $EchoFunc_sig,
                "docstring" => $EchoFunc_doc
                ),

        ));
?>

 

힙합으로 빌드. 

$HPHP_HOME/src/hphp/hphp --input-list=files.list -k 1 --log=3 \
--include-path="." --force=1 --cluster-count=50 \
-v "AllDynamic=true" -v "AllVolatile=true"



/tmp/hphp_ahNFdu 폴더가 생성됨.

80포트를 쓰지 않는다면 sudo 권한은 필요없음. 다음과 같이 구동. 
 

/tmp/hphp_ahNFdu/program -m server -p 8080


아주아주아주 잘 동작하네~~

신기한건 test.php 코드내에서 포함시킨 "xmlrpc.inc", "xmlrpcs.inc" 유니트가 files.list 내에 없어도 제대로 동작한다는 것... 
include() 로 포함시킬 때 함께 들어가게 되는건지... 흠...