-
Notifications
You must be signed in to change notification settings - Fork 3k
Performance Tuning
This page will be a collection of wisdoms about how to get even more speed out of HHVM if you're willing to put some effort in. The percentages are just empirically what average speedups people have seen.
You may also want to look into profiling and optimizing the code actually running on HHVM.
Normally, when HHVM receives a request, it dynamically finds the source code, compiles it and any files it requires on the fly, and then executes them. This is a good flow for development. However, if HHVM can know ahead-of-time what files exist, it can do some precomputation and apply a lot of optimizations that are impossible without ahead-of-time knowledge of all source code. Such optimizations include function inlining (which requires knowing the inlined function won't change), optimizations to the memory layout of objects (which benefits from knowing what member variables may be defined), and many more.
Enabling RepoAuthoritative mode involves pre-compiling all of your source code into a bytecode repo. HHVM then consults only this repo, and not your source code, when servicing web requests. This comes with an often dramatic performance improvement due to the optimizations involved, but means that changes to source code won't take effect until the repo is rebuilt.
Since it's made a bunch of assumptions about what code exists, eval
and create_function
do not work in RepoAuthoritative mode.
As of HHVM 3.8, we provide a shell script to make this easy. To enable RepoAuthoritative mode use the hhvm-repo-auth
script provided with our Debian and Ubuntu packages. Give it the enable
command, followed by the path to your project's source code root -- probably /var/www
or /usr/share/nginx/html
. It will compile the repo, change the relevant HHVM configuration, and restart HHVM all automatically. (Since it changes HHVM configuration, you will probably need to be root to run it.) An example invocation might look like:
sudo hhvm-repo-auth enable /var/www
To disable:
sudo hhvm-repo-auth disable
Although the above script is easy, for more advanced HHVM deployments, the recommended way to use RepoAuthoritative mode is to develop with it disabled, and then to build and deploy a repo, not source code, to production machines.
If you have PHP files file1.php
and file2.php
, you can build a bytecode archive named hhvm.hhbc
by executing this command:
hhvm --hphp -thhbc -o some_dir file1.php file2.php
Now you will have a pre-compiled repo file named some_dir/hhvm.hhbc
. The file hhvm.hhbc
is actually an sqlite database file - you can even view the structure of the file using sqlite. This is similar to a java .jar
or a python .par
file. It is a stand-alone version of your scripts. To run the program file1.php
, use this command:
hhvm -vRepo.Authoritative=true -vRepo.Central.Path=some_dir/hhvm.hhbc file1.php
To run the program file2.php
, use this command:
hhvm -vRepo.Authoritative=true -vRepo.Central.Path=some_dir/hhvm.hhbc file2.php
Note: If you get the error message Unable to find/load systemlib.php
, make sure you are pointing at the hhvm.hhbc
file and not the directory.
The cache locality of the JITted code is very important, and you want all your important endpoints code to be located close to each other in memory. The best way to accomplish this is to pick your most important requests (say 5) and cycle through them all serially until you've done them all 12 times. Something like
for i in `seq 12`; do
while read url; do
curl "$url"
done < important_urls.txt
done
Do this every time you startup the server before it sees user traffic.
TODO: HHVM has a "warmup requests" feature which can do this more effectively, and automatically. We should document it.