PHP vs HHVM Hack vs PHPng

PHP vs HHVM hack vs PHPng

Today PHP has emerged as a rising programming language for web developments. But the php took birth cause of Rasmus Lerdorf’s personal requirements. It was mere a set of C language binary CGI scripts. There the journey started today where we can see PHP as a mature language. It took about 20 years to reach at this stage.

In 1994 Rasmus took its first step and gave rest to Personal home page tools. Rasmus had no intention of making some programming language.The words from Rasmus were “I don’t know how to stop it, there was never any intent to write a programming language. I have absolutely no idea how to write a programming language, I just kept adding the next logical step on the way”. PHP was not originally designed, rather it was developed organically. So it had many inconsistencies in its name, conventions and standards.

Rasmus worked on its tools for having better implementations like database interactions. The code got another re-work and in April of 1996, combining the names of past releases, Rasmus introduced PHP/FI. And from here PHP started its journey as progamming language.It included built-in support for DBM, MYSQL, and Postgres 95 databases, cookies, user-defined function support, and much more. That June, PHP/FI was given a version 2.0 status. An interesting fact about this, however, is that there was only one single full version of PHP 2.0.

And Gutmans and Zeev Suraski of Tel Aviv, Israel needed to submit the e commerce project for university. But as PHP 2.0 was not sufficient enough, so they felt the need to rewrite the whole parser of php. And there we got the PHP we know today i.e PHP 3.0.In June, 1998, with many new developers from around the world joining the effort, PHP 3.0 was announced by the new PHP Development Team as the official successor to PHP/FI 2.0.

By the end of 1998, Zeev and Andy started to rework on PHP. The design goals were to improve performance of complex applications and improve the modularity of PHP’s code base. So Zend Engine fulfilled all of the goals.PHP 4.0 was released in 2000 with the new zend engine and some new features. In addition to performance, PHP 4.0 included other key features such as support for many more web servers, HTTP sessions, output buffering, more secure ways of handling user input and several new language constructs.

PHP 5.0 was released in 2004 after a long development on zend engine. This version was having a new zend engine 2.0. From PHP 5.0 to PHP 5.6, we had a lots of smart programming features in gradual growth. But the Master stroke of PHP 5.0 was the OOPs

The highlights of 5.0 were:

  • Object oriented programming
  • MySQL
  • XML
  • PHP 5.1 came with more features and improvements:
  • A complete rewrite of date handling code, with improved time zone support.
  • Significant performance improvements compared to PHP 5.0.X.
  • PDO extension is now enabled by default.
  • Over 30 new functions in various extensions and built-in functionality.
  • Over 400 various bug fixes.

PHP 5.2 came with following features:

  • New memory manager for the Zend Engine with improved performance and a more accurate memory usage tracking.
  • Input filtering extension was added and enabled by default.
  • JSON extension was added and enabled by default.
  • ZIP extension for creating and editing zip files was introduced.
  • Hooks for tracking file upload progress were introduced.
  • Introduced E_RECOVERABLE_ERROR error mode.
  • Introduced DateTime and DateTimeZone objects with methods to manipulate date/time information.
  • Upgraded bundled SQLite, PCRE libraries.
  • Upgraded OpenSSL, MySQL and PostgreSQL client libraries for Windows installations.
  • Many performance improvements.
  • Over 200 bug fixes.

Then Came PHP 5.3 with some more advance features.

  • Support for namespaces
  • Late static binding
  • Lambda Functions and Closures

We can see the examples below :

1
2
3
$sayhi = function () {
     return "Hello world";
}

Following is the example of closure:

1
2
3
4
 $user = "Philip";
 $greeting = function() use ($user) {
 echo "Hello $user";
 }

The difference between closure and lambda is that lambda is just an anonymous function and that a closure is a function which can access variables not in its parameter list.

  • Syntax additions: NOWDOC, ternary short cut “?:” and jump label (limited goto), __callStatic()
  • Under the hood performance improvements
  • Optional garbage collection for cyclic references
  • Optional mysqlnd PHP native replacement for libmysql
  • Improved Windows support including VC9 and experimental – X64 binaries as well as portability to other supported platforms
  • More consistent float rounding
  • Deprecation notices are now handled via E_DEPRECATED (part of E_ALL) instead of the E_STRICT error level
  • new magic method called “__invoke”
  • Under the hood performance improvements
  • Optional garbage collection for cyclic references

PHP 5.4 had the work in the area of :

  • Traits. A Trait is kind of like a Multiple inheritance in that it allows you to mix Trait classes into an existing class. This means you can reduce code duplication and get the benefits whilst avoiding the problems of multiple inheritance.

Let us see the example code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
trait cURL
{
public function curl($url)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $output = curl_exec($ch);
    curl_close($ch);
    return $output;
}
}
/** Twitter API Class */
class Twitter_API extends API
{
use cURL; // use trait here
public function get($url)
{
    return json_decode($this->curl('http://api.twitter.com/'.$url));
}
}
  • Shorter Array Syntax $fruits = [‘apples’, ‘oranges’, ‘bananas’];
  • Array Dereferencing echo explode(‘ ’, ‘Narinder Kaur’)[1];
  • $this in Anonymous Functions. Previously It was not possible to use $this in anonymous functions, but now we can.
1
2
3
4
5
6
7
8
9
10
11
12
 class Foo
    {
       function hello() {
        echo 'Hello Nettuts!';
       }
   function anonymous()
  {
        return function() {
         $this->hello(); // $this wasn't possible before
        }
       }
  }
  • Callable Typehint: Functions are now able to force parameters to be objects (by specifying the name of the class in the function prototype), interfaces, arrays (since PHP 5.1) or callable (since PHP 5.4). However, if NULL is used as the default parameter value, it will be allowed as an argument for any later call. The code sample is:
1
2
3
4
5
6
7
8
9
10
11
   function my_function(callable $x)
     {
    return $x();
    }
    function my_callback_function(){return 'Hello iZAP!';}
    class Izap{static function hi(){return 'Hello iZAP!';}}
    class Hi{function hello(){return 'Hello iZAP';}}
    echo my_function(function(){return 'Hello iZAP!';}); //       anonymous function
    echo my_function('my_callback_function'); // callback function
    echo my_function(['Izap', 'hi']); // class name, static method
    echo my_function([(new Hi), 'hello']); // class object, method name
  • JsonSerializable Interface
  • Binary Notation
  • Improved performance and reduced memory consumption
  • Built-in webserver in CLI mode to simplify development workflows and testing

Highlights of PHP 5.5 were:

5.6 and the latest version had some awesome functionalities:

  • Constant expressions: It is now possible to provide a scalar expression involving numeric and string literals and/or constants in contexts. For example :
1
2
3
4
5
6
7
8
9
10
const ONE = 1;
const TWO = ONE * 2;
class C {
       const THREE = TWO + 1;
   const ONE_THIRD = ONE / self::THREE;
   const SENTENCE = 'The value of THREE is '.self::THREE;
public function f($a = ONE + self::THREE) {
          return $a;
  }
    }
  • Variadic functions: These type of functions can accept any number of argument without using the ‘func_get_args’. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function variadic_test($name, ...$tools) {
echo "Name:". $name.'<br />';
echo "Count:". count(tools);
}
variadic_test(‘Narinder’, ‘php’);
// Output:
// Name: Narinder
// Count: 1
variadic_test(‘NArinder’, ‘php’, ‘Es’);
// Output:
// Name: Narinder
// Count: 2
variadic_test(‘Narinder’, ‘php’, ‘Es’, ‘Js’);
// Output:
// Name: Narinder
// Count: 3
  • Argument unpacking: We can use the same operator (…) to unpack any argument which is either an array or a set of Traversable objects. For example:
1
2
3
4
5
6
7
8
9
10
11
12
13
function myTools($name, $tool1, $tool2, $tool3) {
    echo "Name:". $name.'<br />';
    echo "Tool1:", $tool1.'<br />';
    echo "Tool2:", $tool2.'<br />';
    echo "Tool3:", $tool3;
}
 $myTools = [‘php’, 'Es', 'Js'];
myTools(‘Narinder', ...$myTools);
// Output:
// Name: Narinder
// Tool1: php
// Tool1: Es
// Tool1: Js
  • Exponentiation via **
  • Phpdbg: An interactive debugger called phpdbg has been added in PHP 5.6.
  • Large file uploads: Now uploads upto 2G are possible and uploads of arbitrary size are now supported.

We have been talking about the zend engine in all of our above discussions. But what exactly is this zend engine, Is it a kind of Hardware or machine or server. This might be a question for all of the freshers in PHP. But as we all know, PHP is developed on the language C, so zend engine is virtual machine, which does not compile the code as the C does, But it provide us the interpreter functionality. Zend engine compiles the PHP code and generates the opcode. and this opcode get execution line by line to give the output from server to browser.

HHVM: Facebook for its requirement to give the fasted response to a large facebook user community, Facebook took many steps towards its goal. Facebook annouced its first stepa in the form of HipHop, A php code transformer, which is used to convert the php code to C++ binaries. Facebook’s HipHop transforms PHP extensions into highly optimized C++ code, which means they run faster when executed. PHP developers at Facebook can write their extensions in PHP, and have HipHop transform it into C++ code, which then can be compiled into speedy binary objects.

The company migrated all its own servers over to HipHop in 2010, claiming that it had cut CPU usage in half. The company released the source code of HipHop so others could use it as well. Facebook also developed their own interpretor aka HPHPi, for the development and debugging phase.As extension and converting to binaries was a long process. Although it was slower but developers can easily code and test in this environment.Recently Facebook announced the solution of this slowness too with the release of HHVM. With HHVM Facebook tried to gave the flexibility of scripting language and speed of compiled language. HHVM is basically a technology which make use of JIT compiler. just-in-time compilation (JIT), also known as dynamic translation, is compilation done during execution of a program – at run time – rather than prior to execution. According to Facebook, this PHP execution engine is 60 percent faster than its current PHP interpreter and uses 90 percent less memory.

phpng: The new branch of php which is in romours to be the base code for php7. Wait where is php 6. php 6 was there in a plan to work around for unicoding. But with the release of phpng, the new direction given to php is the performance gains. Zend engine developers tried to work in the same section that Facebook did, that is the JIT, but because of the complexities of zend engine in current time, it did not give any feasible outcome, but they still gave performance with new kind of approaches, which is basically the way the memory is allocted to the php. Memory allocation is basically a task of data structure changes in zvals and Hashtables.

zvals are the data structures used to represent the values in php.

The new zval implementation: Lets take a quick look at the new zval structure and see how it differs from the old one. The zval struct is defined as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct _zval_struct {
  zend_value value;
union {
  struct {
      ZEND_ENDIAN_LOHI_4(
          zend_uchar type,
          zend_uchar type_flags,
          zend_uchar const_flags,
          zend_uchar reserved)
  } v;
  uint32_t type_info;
} u1;
union {
  uint32_t var_flags;
  uint32_t next;       /* hash collision chain */
  uint32_t cache_slot; /* literal cache slot */
  uint32_t lineno;     /* line number (for ast nodes) */
} u2;
};

The zval structure has three parts: The first member is the value. The zend_value union is 8 bytes large and can store different kinds of values, including integers, strings, arrays, etc. What is actually stored in there depend on the zval type. The second part is the 4 byte type_info, which consists of the actual type (like IS_STRING or IS_ARRAY), as well as a number of additional flags providing information about this type. E.g. if the zval is storing an object, then the type flags would say that it is a non-constant, refcounted, garbage-collectible, non-copying type. The last 4 bytes of the zval structure are normally unused. However in special contexts this space is used to store some extra information. E.g. hashtables use it to store the next element in the collision resolution chain.

The old structure is :

1
2
3
4
5
6
typedef struct _zval_struct {
zvalue_value value;
zend_uint refcount__gc;
zend_uchar type;
zend_uchar is_ref__gc;
} zval;

If we compare the old and new zval structure, the new zval structure no longer stores a refcount as zvals themselves are no longer individually allocated. Instead the zval is directly embedded into whatever is storing it (e.g. a hashtable bucket). While the zvals themselves no longer use refcounting, complex data types like strings, arrays, objects and resources still use them. Effectively the new zval design has pushed out the refcount from the zval to the array/object/etc. There are a number of advantages to this approach, some of them listed in the following:

Zvals storing simple values (like booleans, integers or floats) no longer require any allocations. So this saves the allocation header overhead and improves performance by avoiding unnecessary allocs and frees and improving cache locality. Zvals storing simple values don’t need to store a refcount.

A Hash Table is an ubiquitous data structure, which essentially solves the problem that computers can only directly represent continuous integer-indexed arrays, whereas programmers often want to use strings or other complex types as keys.The concept behind a hash table is very simple: The string key is run through a hashing function, which returns an integer. This integer is then used as an index into a “normal” array. The problem is that two different strings can result in the same hash, as the number of possible strings is virtually infinite while the hash is limited by the integer size. As such hash tables need to implement some kind of collision resolution mechanism. Now the work is on data structure part of the hashtable, how the old hashtables and new hash tables are implements and allocated in php.

The values stored in the hash tables are called buckets.if we look at the data structure of the bucket : New Bucket Structure:

1
2
3
4
5
typedef struct _Bucket {
zend_ulong        h;
zend_string      *key;
zval              val;
} Bucket;
  • zvals are directly used in the the buckets, so no separate allocations or de-allocations are needed. So reduced overheads. But previously there was no such directly embedding as we can see in the old format shown ahead.
  • pListNext, pListLast are no more used in zvals structure which previously were used for collision resolutions techniques.
  • pNext, pLast are no more used in zvals structure which were used for maintaining the order of hash tables and eventually the order of keys in arrays.

So after having a brief introduction to the changes made,we can conclude that phpng is basically a performance release. No new features have been added. new implementation is faster: First of all we need less allocations. Depending on whether or not values are shared we save two allocations per element. Allocations being rather expensive operations this is quite significant.

Array iteration in particular is now more cache-friendly, because it’s now a linear memory traversal, instead of a random-access linked list traversal.

Comments