Leading up to the release of the first stable version of our PHP compiler, we are now implementing the first various compiler optimizations. Read more about them in this blog and why you should update or try PeachPie 0.9.45!
As usually, this release fixes some issues, adds new standard PHP features that were required to run certain frameworks and also introduces the first optimizations the compiler can perform to maximize the performance of the compiled PHP apps.
There are some nice examples of what the compiler can do, and what the consequences of that can be. Mostly the compiler now evaluates more conditions and therefore resolves more unreachable code; not only does it make the resulting assembly smaller, but since the unreachable code may contain alternative declarations of functions and classes, the compiler now ignores those declarations, getting rid of potential ambiguities and avoiding a dynamic resolution in run-time.
Below is a list of some of the optimization we’ve tried so far. This is only a small fraction of possible performance improvements to make, but our internal benchmarks show that these have already sped up e.g. the loading of a WordPress page by about 8%!
- string concatenation is resolved in compile time if possible
- more complex conditions are evaluated
ini_get()evaluated in compile time in some cases. Usually if we know the option is not supported and ini_get() would always return FALSE
requirecan be evaluated as well; since PeachPie compiles script files into .NET static methods, they can be called directly instead of looking into a hash table and resolving the file path in run time
callablescan be evaluated in compile time; this is more complex and maybe it deserves its own blog post. When a constant value is about to be converted to a callable – e.g.
array_map('cube', $a);– and since every PHP function is compiled into a .NET method, we can resolve the function name – ‘cube’ – and use the CLR delegate directly. The delegate is pre-allocated and results in zero overhead instead of resolving the function in run-time
Most of these optimizations only take effect when compiling the PHP app in release mode (on the command line:
dotnet build -c release). We will continue to implement these types of optimizations to release a version 1.0 that’s as performant as possible given the resources we have.
More so than just fixing issues, we’re constantly working on allowing real-world legacy PHP applications to run on .NET and .NET Core. While migrating code such as Laravel, Symfony, PHPUnit, WordPress and related plugins, and when compiling our clients’ really old PHP apps, we have implemented the following:
- XInclude functionality (XML extension) (thanks TomatorCZ)
- PHP 7.4 syntax (not all features implemented yet, however)
??=operator (PHP 7.4)
array_merge()accepts zero arguments (PHP 7.4)
ReflectionProperty.setValue()overload with 1 parameter
As always, we continually fix issues our community submits on GitHub or that we run into when working on our clients’ projects. Here is a short list of some of the more prominent issues we encountered and fixed:
- the compiler crashed due to an unsecured critical section in logging!
- the compiler crashed on a nullref exception in case of a syntax error
var_export()did not escape outputted strings
- the compiler treated all primitive types as nullable
get_parent_class()returned invalid values when used without arg
As always, we welcome any feedback, contributions, issues, questions and we continue to implement features as needed by both our clients and our community. If you’re a .NET performance connoisseur, please do consider submitting PRs with any low-level optimizations you can think of!