Changing Zend Engine distribution mode to improve PHP performance

Source: Internet
Author: User
Tags sapi test script example
Starting from PHP5.1, PHP provides an interface for users to select a distribution method for ZendVM execution. in my previous articles, I also mentioned this. when the Zend virtual machine is running, the opcode of each opline in the op_array generated by the compilation will be distributed to the corresponding processing... "> <LINKhref =" http://www.php100.com/

 

Starting from PHP5.1, PHP provides an interface for users to select the Zend VM execution distribution method.

I have mentioned this in my previous articles. when the Zend virtual machine is running, the opcode of each opline in the compiled op_array is distributed to the corresponding processor (defined by zend_vm_def.h) for execution. the distribution process can be divided into CALL, SWITCH, and GOTO.

By default, the CALL method is used, that is, all opcode processors are defined as functions and then virtual machines are called. this method is a traditional method and is generally considered the most stable method.

The SWITCH mode and the GOTO mode have the same meaning as the naming method. the opcode is distributed to the corresponding processing logic (segment) through the switch and goto methods respectively ).

The official description is as follows:

CALL-Uses function handlers for opcodes

SWITCH-Uses switch () statement for opcode dispatch

GOTO-Uses goto for opcode dispatch (threaded opcodes architecture)

GOTO is usually (depends on CPU and compiler) faster than SWITCH, which

Tends to be slightly faster than CALL.

CALL is default because it doesn' t take very long to compile as opposed

To the other two and in general the speed is quite close to the others.

How much efficiency can be improved if the GOTO method is used?

Today I will test the script ghost. php in various ways.

The first proof is that the GOTO compilation time is significantly higher than that of the other methods. at first, I compiled it on a virtual machine and Hangup (compile) each time ), finally, I had to change to a strong physical machine. after about three minutes, the compilation was successful ..

Test environment:

 

PHP 5.3.0 Linux

AMD Opteron (tm) Processor 270 (2G) X 4 6G Memory

 

Compilation parameters:

 

./Configure -- with-zend-vm = CALL/GOTO/SWITCH

 

The test results are as follows (values are obtained three times ):

CALL method:

 

Laruence@dev01.tc $ sapi/cli/php composer. php

Easy 0.358

Simplecall 0.418

Simplecuall 0.405

Simpleudcall 0.424

Mandel 1.011

Mantel2 1.238

Ackermann (7) 0.375

Ary (1, 50000) 0.083

Army2 (50000) 0.075

Ary3 (2000) 0.561

Fiber (30) 1.156

Hash1 (50000) 0.114

Hash2 (500) 0.091

Heapsort (20000) 0.270

Matrix (20) 0.276

Nestedloop (12) 0.599

Sieve (30) 0.350

Strcat (200000) 0.039

------------------------

Total 7.844

 

SWITCH Mode:

 

Laruence@dev01.tc $ sapi/cli/php composer. php

Easy 0.393

Simplecall 0.414

Simplecuall 0.424

Simpleudcall 0.445

Mandel 1.007

Mantel2 1.254

Ackermann (7) 0.392

Ary (1, 50000) 0.084

Army2 (50000) 0.073

Ary3 (2000) 0.593

Fiber (30) 1.185

Hash1 (50000) 0.120

Hash2 (500) 0.092

Heapsort (20000) 0.285

Matrix (20) 0.295

Nestedloop (12) 0.678

Sieve (30) 0.359

Strcat (200000) 0.042

------------------------

Total 8.138

 

GOTO method:

 

Laruence@dev01.tc $ sapi/cli/php composer. php

Easy 0.306

Simplecall 0.373

Simplecuall 0.369

Simpleudcall 0.385

Mandel 0.879

Mantel2 1.132

Ackermann (7) 0.356

Ary (1, 50000) 0.081

Army2 (50000) 0.073

Ary3 (2000) 0.525

Fiber (30) 1.043

Hash1 (50000) 0.111

Hash2 (500) 0.088

Heapsort (20000) 0.247

Matrix (20) 0.247

Nestedloop (12) 0.519

Sieve (30) 0.331

Strcat (200000) 0.037

------------------------

Total 7.103

 

It can be seen that the GOTO method is the fastest, and the SWITCH method is the slowest. it is slightly different from the official description.

Compared with its default CALL method, the GOTO method improves performance significantly.

Therefore, if you want to enable PHP to use the mechanism and change the Zend VM distribution method, you can also consider it as a factor.

Appendix:

Use the GOTO configure option:

 

-- With-zend-vm = GOTO

 

You can also use the following in the Zend Directory:

 

Php zend_vm_gen.php -- with-vm-kind = [CALL | GOTO | SWITH]

 

Test script example. php

 

  

/**

* PHP Perf submit Test Script

*/

Function simple (){

$ A = 0;

For ($ I = 0; I I <1000000; $ I ++)

$ A ++;

$ Thisisanotherlongname = 0;

For ($ thisisalongname = 0; $ thisisalongname <1000000; $ thisisalongname ++)

$ Thisisanotherlongname ++;

}

/****/

Function simplecall (){

For ($ I = 0; I I <1000000; $ I ++)

Strlen ("hallo ");

}

/****/

Function hallo ($ ){

}

Function simpleucall (){

For ($ I = 0; I I <1000000; $ I ++)

Hallo ("hallo ");

}

/****/

Function simpleudcall (){

For ($ I = 0; I I <1000000; $ I ++)

Hallo2 ("hallo ");

}

Function hallo2 ($ ){

}

/****/

Function mandel (){

$ W1 = 50;

$ H1 = 150;

$ Recen =-. 45;

$ Imcen = 0.0;

$ R = 0.7;

$ S = 0; $ rec = 0; $ imc = 0; $ re = 0; $ im = 0; $ re2 = 0; $ im2 = 0;

$ X = 0; $ y = 0; $ w2 = 0; $ h2 = 0; $ color = 0;

$ S = 2 * $ r/$ w1;

$ W2 = 40;

$ H2 = 12;

For ($ y = 0; $ y <= $ w1; $ y = $ y + 1 ){

$ Imc = $ s * ($ y-$ h2) + $ imcen;

For ($ x = 0; $ x <= $ h1; $ x = $ x + 1 ){

$ Rec = $ s * ($ x-$ w2) + $ recen;

$ Re = $ rec;

$ Im = $ imc;

$ Color = 1000;

$ Re2 = $ re * $ re;

$ Im2 = $ im * $ im;

While ($ re2 + $ im2) <1000000) & $ color> 0 )){

$ Im = $ re * $ im * 2 + $ imc;

$ Re = $ re2-$ im2 + $ rec;

$ Re2 = $ re * $ re;

$ Im2 = $ im * $ im;

$ Color = $ color-1;

}

If ($ color = 0 ){

Print "_";

} Else {

Print "#";

}

}

Print"
";

Flush ();

}

}

/****/

Function mandel2 (){

$ B = ".:,;! />) | & IH % *#";

// Float r, I, z, Z, t, c, C;

For ($ y = 30; printf ("\ n"), $ C = $ y * 0.1-1.5, $ y --;){

For ($ x = 0; $ c = $ x * 0.04-2, $ z = 0, $ Z = 0, $ x ++ <75 ;){

For ($ r = $ c, $ I = $ C, $ k = 0; $ t = $ z * $ z-$ Z * $ Z + $ r, $ Z = 2 * $ z * $ Z + $ I, $ z = $ t, $ k <5000; $ k ++)

If ($ z * $ z + $ Z * $ Z> 500000) break;

Echo $ B [$ k % 16];

}

}

}

/****/

Function Ack ($ m, $ n ){

If ($ m = 0) return $ n + 1;

If ($ n = 0) return Ack ($ M-1, 1 );

Return Ack ($ m-1, Ack ($ m, ($ n-1 )));

}

Function ackermann ($ n ){

$ R = Ack (3, $ n );

Print "Ack (3, $ n): $ r \ n ";

}

/****/

Function ary ($ n ){

For ($ I = 0; $ I <$ n; $ I ++ ){

$ X [$ I] = $ I;

}

For ($ I = $ n-1; $ I >=0; $ I --){

$ Y [$ I] = $ X [$ I];

}

$ Last = $ n-1;

Print "$ Y [$ last] \ n ";

}

/****/

Function ary2 ($ n ){

For ($ I = 0; $ I <$ n ;){

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

$ X [$ I] = $ I; ++ $ I;

}

For ($ I = $ n-1; $ I >=0 ;){

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

$ Y [$ I] = $ X [$ I]; -- $ I;

}

$ Last = $ n-1;

Print "$ Y [$ last] \ n ";

}

/****/

Function ary3 ($ n ){

For ($ I = 0; $ I <$ n; $ I ++ ){

$ X [$ I] = $ I + 1;

$ Y [$ I] = 0;

}

For ($ k = 0; $ k <1000; $ k ++ ){

For ($ I = $ n-1; $ I >=0; $ I --){

$ Y [$ I] + = $ X [$ I];

}

}

$ Last = $ n-1;

Print "$ Y [0] $ Y [$ last] \ n ";

}

/****/

Function fibo_r ($ n ){

Return ($ n <2 )? 1: fibo_r ($ n-2) + fibo_r ($ n-1 ));

}

Function fibo ($ n ){

$ R = fibo_r ($ n );

Print "$ r \ n ";

}

/****/

Function hash1 ($ n ){

For ($ I = 1; $ I <= $ n; $ I ++ ){

$ X [dechex ($ I)] = $ I;

}

$ C = 0;

For ($ I = $ n; $ I> 0; $ I --){

If ($ X [dechex ($ I)]) {$ c ++ ;}

}

Print "$ c \ n ";

}

/****/

Function hash2 ($ n ){

For ($ I = 0; $ I <$ n; $ I ++ ){

$ Hash1 ["foo _ $ I"] = $ I;

$ Hash2 ["foo _ $ I"] = 0;

}

For ($ I = $ n; $ I> 0; $ I --){

Foreach ($ hash1 as $ key => $ value) $ hash2 [$ key] + = $ value;

}

$ First = "foo_0 ";

$ Last = "foo _". ($ n-1 );

Print "$ hash1 [$ first] $ hash1 [$ last] $ hash2 [$ first] $ hash2 [$ last] \ n ";

}

/****/

Function gen_random ($ n ){

Global $ LAST;

Return ($ n * ($ LAST = ($ LAST * IA + IC) % IM)/IM );

}

Function heapsort_r ($ n, & $ ra ){

$ L = ($ n> 1) + 1;

$ Ir = $ n;

While (1 ){

If ($ l> 1 ){

$ Rra = $ ra [-- $ l];

} Else {

$ Rra = $ ra [$ ir];

$ Ra [$ ir] = $ ra [1];

If (-- $ ir = 1 ){

$ Ra [1] = $ rra;

Return;

}

}

$ I = $ l;

$ J = $ l <1;

While ($ j <= $ ir ){

If ($ j <$ ir) & ($ ra [$ j] <$ ra [$ j + 1]) {

$ J ++;

}

If ($ rra <$ ra [$ j]) {

$ Ra [$ I] = $ ra [$ j];

$ J + = ($ I = $ j );

} Else {

$ J = $ ir + 1;

}

}

$ Ra [$ I] = $ rra;

}

}

Function heapsort ($ N ){

Global $ LAST;

Define ("IM", 139968 );

Define ("IA", 3877 );

Define ("IC", 29573 );

$ LAST = 42;

For ($ I = 1; $ I <= $ N; $ I ++ ){

$ Ary [$ I] = gen_random (1 );

}

Heapsort_r ($ N, $ ary );

Printf ("%. 10f \ n", $ ary [$ N]);

}

/****/

Function mkmatrix ($ rows, $ cols ){

$ Count = 1;

$ Mx = array ();

For ($ I = 0; $ I <$ rows; $ I ++ ){

For ($ j = 0; $ j <$ cols; $ j ++ ){

$ Mx [$ I] [$ j] = $ count ++;

}

}

Return ($ mx );

}

Function mmult ($ rows, $ cols, $ m1, $ m2 ){

$ M3 = array ();

For ($ I = 0; $ I <$ rows; $ I ++ ){

For ($ j = 0; $ j <$ cols; $ j ++ ){

$ X = 0;

For ($ k = 0; $ k <$ cols; $ k ++ ){

$ X + = $ m1 [$ I] [$ k] * $ m2 [$ k] [$ j];

}

$ M3 [$ I] [$ j] = $ x;

}

}

Return ($ m3 );

}

Function matrix ($ n ){

$ SIZE = 30;

$ M1 = mkmatrix ($ SIZE, $ SIZE );

$ M2 = mkmatrix ($ SIZE, $ SIZE );

While ($ n --){

$ Mm = mmult ($ SIZE, $ SIZE, $ m1, $ m2 );

}

Print "{$ mm [0] [0]} {$ mm [2] [3]} {$ mm [3] [2]} {$ mm [4] [4 ]} \ n ";

}

/****/

Function nestedloop ($ n ){

$ X = 0;

For ($ a = 0; $ a <$ n; $ a ++)

For ($ B = 0; $ B <$ n; $ B ++)

For ($ c = 0; $ c <$ n; $ c ++)

For ($ d = 0; $ d <$ n; $ d ++)

For ($ e = 0; $ e <$ n; $ e ++)

For ($ f = 0; $ f <$ n; $ f ++)

$ X ++;

Print "$ x \ n ";

}

/****/

Function sieve ($ n ){

$ Count = 0;

While ($ n --> 0 ){

$ Count = 0;

$ Flags = range (0,8192 );

For ($ I = 2; I I <8193; $ I ++ ){

If ($ flags [$ I]> 0 ){

For ($ k = $ I + $ I; $ k <= 8192; $ k + = $ I ){

$ Flags [$ k] = 0;

}

$ Count ++;

}

}

}

Print "Count: $ count \ n ";

}

/****/

Function strcat ($ n ){

$ Str = "";

While ($ n --> 0 ){

$ Str. = "hello \ n ";

}

$ Len = strlen ($ str );

Print "$ len \ n ";

}

/*****/

Function getmicrotime ()

{

$ T = gettimeofday ();

Return ($ t ['SEC '] + $ t ['usec']/1000000 );

}

Function start_test ()

{

Ob_start ();

Return getmicrotime ();

}

Function end_test ($ start, $ name)

{

Global $ total;

$ End = getmicrotime ();

Ob_end_clean ();

$ Total + = $ end-$ start;

$ Num = number_format ($ end-$ start, 3 );

$ Pad = str_repeat ("", 24-strlen ($ name)-strlen ($ num ));

Echo $ name. $ pad. $ num. "\ n ";

Ob_start ();

Return getmicrotime ();

}

Function total ()

{

Global $ total;

$ Pad = str_repeat ("-", 24 );

Echo $ pad. "\ n ";

$ Num = number_format ($ total, 3 );

$ Pad = str_repeat ("", 24-strlen ("Total")-strlen ($ num ));

Echo "Total". $ pad. $ num. "\ n ";

}

$ T0 = $ t = start_test ();

Simple ();

$ T = end_test ($ t, "simple ");

Simplecall ();

$ T = end_test ($ t, "simplecall ");

Simpleucall ();

$ T = end_test ($ t, "simpleucall ");

Simpleudcall ();

$ T = end_test ($ t, "simpleudcall ");

Mandel ();

$ T = end_test ($ t, "mandel ");

Mandel2 ();

$ T = end_test ($ t, "mandel2 ");

Ackermann (7 );

$ T = end_test ($ t, "ackermann (7 )");

Ary (50000 );

$ T = end_test ($ t, "ary (50000 )");

Ary2 (50000 );

$ T = end_test ($ t, "ary2 (50000 )");

Ary3 (2000 );

$ T = end_test ($ t, "ary3 (2000 )");

Fibo (30 );

$ T = end_test ($ t, "fibo (30 )");

Hash1 (50000 );

$ T = end_test ($ t, "hash1 (50000 )");

Hash2 (500 );

$ T = end_test ($ t, "hash2 (500 )");

Heapsort (20000 );

$ T = end_test ($ t, "heapsort (20000 )");

Matrix (20 );

$ T = end_test ($ t, "matrix (20 )");

Nestedloop (12 );

$ T = end_test ($ t, "nestedloop (12 )");

Sieve (30 );

$ T = end_test ($ t, "sieve (30 )");

Strcat( 200000 );

$ T = end_test ($ t, "strcat( 200000 )");

Total ($ t0, "Total ");

?>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.