에몽이

미리보는 PHP 7 PHP7의 차이점,장점 본문

web/php

미리보는 PHP 7 PHP7의 차이점,장점

ian_hodge 2017. 4. 14. 14:11

PHP7이 올해 10월 릴리즈를 목표로 최근 베타버전이 공개 되었습니다. 2004년에 PHP 5.0이 릴리즈 된 이후 거의 10년만의 메이저 버전이 업데이트 입니다.

현재 PHP의 최종 버전은 5.6이며, PHP6을 Unicode 네이티브 문자열이 모든 언어와 플랫폼에 지원이 가능하도록 목표로 하여 진행 했지만 자원낭비가 심한 문제가 있어 2010년에 개발을 중단하였습니다. 이후 2014년 초에 PHP 성능 개선 프로젝트인 PHPNG(Next Generation)로 브랜치를 생성하였고, 개발 중 많은 개선사항이 있어 결국 2014년 8월에 PHP7 기반 프로젝트로 채택되었습니다. 6버전 없이 바로 7로 채택된 이유는 RFC에서 투표를 통해 개발 중단된 6과의 혼동을 원치 않아서라고 합니다.
 
PHP7에서 어떠한 내용이 변경되었는지 알아보도록 하겠습니다.



Facebook의 HHVM와 PHP7

본격적인 이야기에 앞서 Zend Engine과 경쟁이 되는 HHVM에 대해서 알아보겠습니다.
페이스북은 초기에 대부분 PHP로 만들어져 빠른 개발의 장점이 있었으나, 다른 언어에 비해 느리다는 단점으로 HHVM(HipHop Virtual Machine)을 만들었고 2011년에 최초로 공개하며 Zend Engine의 경쟁자가 되었습니다. 이후 2014년에는 Hack Language를 공개해 PHP를 확장하며 기존 PHP의 호환성을 유지하였고, JIT 컴파일을 통해 더욱 향상된 성능을 선보였습니다. 이로 인해 현재 여러 기업에서 상용 서비스에 이용하는 사례가 많아지고 있습니다. 

이러한 현실을 의식하듯 zend사에서는 PHP7에 대해 "HHVM보다 일반적으로 빠르다." 라고 소개하며 이목을 집중시켰고, 벤치마킹 자료 또한 "PHP7 vs HHVM"의 비교를 통해 HHVM보다 나은 속도를 목표로 했음을 강조했습니다. HHVM은 PHP7에 많은 영향을 끼쳤다는것을 짐작할 수 있습니다.



PHP7 성능

Zend Engine 개발사인 Zend사에서 "PHP7에서 반드시 알아야 할 5가지"라는 제목으로 주요 변경 사항에 대해 게재하였습니다. 성능 부분에서 PHP5.6버전에 비해 25% ~ 70%의 성능 향상을 기대할 수 있습니다. 


 


<PHP에서 반드시 알아야 할 5가지>

출처 : https://www.zend.com/en/resources/php-7



Zend사는 개발 중에도 지속적으로 벤치마킹 자료를 업데이트하고 있습니다. 벤치마킹은 PHP를 기반으로 돌아가는 어플리케이션 및 프레임웍, 라이브리 등으로 테스트 한 것이며, 다음은 최근 마지막으로 공개된 2015년 6월 24일 벤치마킹 자료 중 Wordpress와 Laravel 프레임웍에 대한 초당 응답속도를 그래프화 한 것입니다.


 
< Wordpress와 Laravel 프레임웍에 대한 초당 응답속도>


PHP 5.6과 7을 비교해보면 2배 빠르며, HHVM과 비교 할 땐 wordpress가 거의 비슷하지만 많이 따라 잡았음을 확인 할 수 있습니다. 10월, 정식버전이 공식 배포될 때에는 HHVM에 비해 더 나은 성능을 보여줄 수 있을지 기대됩니다.

알파버전 및 릴리즈 일정은 RFC php7timeline에서 확인 할 수 있습니다.



Zend 엔진 개선

1. zval (zend value) 구조체 개선
PHP7의 성능개선에서 제일 큰 부분을 차지하고 있는 부분으로, 초기에 JIT 컴파일로 성능향상을 시도했지만 재검토 결과 구조체 변경이 더 효과적인 것으로 결론이 나와, 변수를 저장하는 zval의 구조체를 개선하여 기존 24바이트에서 16바이트로 줄여 최적화 하였습니다. 하나의 예로 정수형에 대한 구조체가 아래와 같이 변경되었습니다.
 

<PHP5의 zval 구조체>



PHP5에선 하나의 row당 8bytes(64bit)로 * 3row 일때 24bytes가 할당 되지만, "unused"로 인해 10(8+2)bytes가 낭비되고 있습니다. 또한 zval pointer로 인해 총 32bytes를 소비하게 됩니다.





<PHP7의 zval 구조체>



PHP7은 8bytes * 2row = 16bytes가 할당되며, zval에 대한 포인트가 없어 16bytes에서 그치게 되어, 훨씬 효율적으로 메모리가 사용되고 있습니다.



2. 컴파일 과정에 AST(Abstract Syntax Tree) 도입

PHP 컴파일 과정에 AST단계를 추가함으로써 문법해석을 유연하게 대응하여 opcode를 최적화 할 수 있도록 하였습니다.




<컴파일 과정에 AST를 도입한 PHP7>


3. 배열(HashTable / Bucket)
- 해시 테이블 사이즈가 72bytes에서 56bytes로 감소
버킷 사이즈가 72bytes에서 32bytes로 감소
모든 버킷에 대해 메모리할당은 한번만 처리
배열 값 요소들이 버킷에 포함
향상된 데이터로 CPU캐시 실패율 감소


4. New Memory Manager
- PHP5 메모리 관리자는 CPU 시간의 20 % 이상을 소비
메모리 할당자를 dlmalloc에서 jemalloc으로 전환 
할당된 메모리의 오버헤드 최소화
linked list 대신 biteset을 사용
훨씬 더 CPU cache에 친화됨
Memory Manager 오버헤드 5%감소


5. Fast Parameter Parsing API
- CPU시간의 5%를 zend_parse_parameters() 에 소요
- 간단한 기능 추가로 오버헤드 90%이상 줄임


6. 비동기 프로그래밍
네트워크, 데이터베이스, 파일 및 타이머에 대한 접근을 비동기로 작업 지원


7. 그밖의 개선
New HashTable iteration API
배열 중복 최적화
PCRE with JIT 지원
strtr () 수정
strlen(), defined() inlining
serialize() 최적화
IND_GLOBAL instead of FETCH + ASSIGN_REF




언어 변경사항
1. 결합 비교 연산자 도입(<=>)
펄, 루비, 그루비에 있는 <=> 복합연산자가 도입됩니다. 
strcmp()와 비슷한 동작을 하는 함수인데 문자 타입에 대한 비교를 하는 strcmp()와는 달리 배열이나 객체등 여러 자료형에 사용할 수 있는 차이가 있으며, usort() 함수의 콜백 함수와 같이 정렬 기능을 만들때 효율적입니다.

 operator

 <=> equivalent

 $a < $b

 ($a <=> $b) === -1

 $a <= $b

 ($a <=> $b) === -1 || ($a <=> $b) === 0

 $a == $b

 ($a <=> $b) === 0

 $a != $b

 ($a <=> $b) !== 0

 $a >= $b

 ($a <=> $b) === 1 || ($a <=> $b) === 0

 $a > $b

 ($a <=> $b) === 1



 

1
2
3
4
5
6
function order_func($a, $b) { //PHP5
    return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
}
function order_func($a, $b) { //PHP7
    return $a <=> $b;
}



2. 리턴타입 선언 및 스칼라 타입 힌트 제공

5버전에 도입된  파라메타 타입 힌트에 이어 리턴 타입도 선언할 수 있습니다. (Hack language에선 이미 지원하고 있는 사항입니다.)


1
2
3
function foo(): array {
    return [123];
}



배열과 객체에서만 사용할 수 있었던 타입힌트를 스칼라타입(int, float, string, bool) 힌트를 사용 할 수 있습니다.


1
2
3
4
function foo (int $ i) {
    echo $ i;
}
foo (3); //3



문서 상단에 declare(strict_types=1); 선언 시, 타입에 대해 자동 변환으로 느슨하게 처리되던 것이 엄격한 타입체크를 할 수 있게 됩니다. 지금까지 타입에 대해 엄격하지 않은 다른 언어처럼 타입선언을 명시적으로 처리하기 위함인 것 같습니다.


1
2
3
4
5
6
7
8
9
declare(strict_types=1);
function foobar(): int {
    return 1.0// strictly type-checked return
}
class baz {
    function foobar(): int {
        return 1.0// strictly type-checked return
    }
}



3. 널 병합 연산자 (??)
isset함수를 이용한 3항 연산자와 동일하며, 축약형인 "?:" 와 비슷하지만 정의되지 않은 변수에 대해서도 오류가 나지 않습니다.


1
2
3
4
5
6
7
8
9
$a = NULL;
$b = 1;
$c = 2;
  
echo isset($a) ? $a : $b; //1
echo $a ?? $b; // 1
echo $c ?? $b; // 2
echo $a ?? $b ?? $c; // 1
echo $a ?? $x ?? $c; // 2




4. 치명적인 오류개선
오류를 처리하지 못하고 종료되는 현상을 EngineException 예외를 추가하여 개선하였습니다.


1
2
3
4
5
6
//PHP5
function call_method($obj) {
    $obj->method();
}
call_method(null);
// Fatal error: Call to a member function method() on a non-object


 

1
2
3
4
5
6
//PHP7
try {
    call_method(null);
catch (EngineException $e) {
    echo "Exception: {$e->getMessage()}\n";
}// Exception: Call to a member function method() on a non-object



5. 익명함수

별도 클래스 정의 없이 바로 객체생성을 할 수 있도록 익명함수를 지원합니다.


1
2
3
4
5
6
7
class Foo {}
$ child = new class extends Foo {};
var_dump ($ child instanceof Foo); // true
 
$ obj = new class {public $ foo = 3; public $ bar = 4;};
var_dump ($ obj -> foo); // int (3)
var_dump ($ obj -> bar); // int (4)



6. Uniform Variable Syntax

함수 및 메서드 중첩 호출 지원합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function foo() {
     return function() {
         var_dump("test");
     };
 }
 foo()();
 
$foo()['bar']()
[$obj1, $obj2][0]->prop
getStr(){0}
  
// :: 중첩지원
$foo['bar']::$baz
$foo::$bar::$baz
$foo->bar()::baz()
  
// support nested ()
foo()()
$foo->bar()()
Foo::bar()()
$foo()()
  
// 임의 표현식에 대한 지원
(...)['foo']
(...)->foo
(...)->foo()
(...)::$foo
(...)::foo()
(...)()
  
// 실용적인 예제
(function() { ... })()
($obj->closure)()
 
// 문법 변경 예          // old meaning            // new meaning
$$foo['bar']['baz']     ${$foo['bar']['baz']}     ($$foo)['bar']['baz']
$foo->$bar['baz']       $foo->{$bar['baz']}       ($foo->$bar)['baz']
$foo->$bar['baz']()     $foo->{$bar['baz']}()     ($foo->$bar)['baz']()
Foo::$bar['baz']()      Foo::{$bar['baz']}()      (Foo::$bar)['baz']()



7. closure :: call ()

외부 클래스의 함수를 인스턴스 메소드 처럼 호출 할 수 있습니다.


1
2
3
4
5
6
7
8
9
class Foo {
    private $ x = 3;
}
 
$ foo = new Foo;
$ foobar = function () {
    var_dump ($ this -> x);
};
$ foobar->call($foo); // prints int (3)



8. Windows 플랫폼에 64Bit 지원

기존 64bit 윈도우 환경이 LLP64 플랫폼으로 인해 정수가 32bit로 제한되었던 부분이 64bit로 지원할수 있게 되었습니다.


9. 암호학적으로 안전한 난수 생성기(CSPRNG)
CSPRNG(Cryptographically Secure Random Number Generator)는 암호의 안전성을 보장하며 예측 불가능한 난수를 생성기로 아래와 같은 함수가 추가되었습니다.

1
2
3
4
//임의의 16바이트 문자열을 반환
random_bytes (16);
//5에서 10까지의 무작위 정수 반환
random_int (510);





마치며
PHP7에 채택된 RFC는 48개로, 이전 버전인 5.6에서의 17개 보다 훨신 많아 큰 변화가 있지만, 코드 수정 없이 버전 업데이트만으로 운영이 가능하도록 기존 버전과 높은 호환성을 유지한다고 합니다.
올해 20주년인 PHP는 w3techs 통계자료를 봤을 때, 서버 사이드 언어로 전세계 시장점유율 81.8%를 차지하고 있지만, 최초 개인홈페이지용으로 간단한 C API 통신을 위해 만들어졌기에, 초기 설계가 체계적이지 못한 부분이 있어 보안측면이나 엔터프라이즈급 규모에서는 외면 받는 언어이기도 합니다. 하위버전 호환성 유지로 인해 PHP7에서도 단점을 완전히 버리지는 못하였지만, HACK의 문법이 같이 적용되고 2배 빠른 성능향상으로 이번 업데이트를 통해 긍정적인 언어로 거듭날 수 있을지 앞으로의 행보가 기대됩니다.




 참고
 
출처:http://m.blog.naver.com/tmondev/220484007697


'web > php' 카테고리의 다른 글

php 파일 업로드 오류 이유  (1) 2017.01.12
curl  (0) 2017.01.03
우측의 페이지 따라다니는 사이드 바  (0) 2016.11.05
Comments