facebook / hhvm

A virtual machine for executing programs written in Hack.
https://hhvm.com
Other
18.16k stars 2.99k forks source link

Using Warmup requests and Warmup docs #5312

Closed simoncast closed 9 years ago

simoncast commented 9 years ago

We are trying to use the warmup requests capability of HHVM as detailed in this <a href=https://codeascraft.com/2015/04/06/experimenting-with-hhvm-at-etsy/">article by Etsy and mentioned on the HHVM wiki in passing.

We've tried using both HDF and ini files but neither is calling the warmup doc when HHMV is restarted. How do you go about using the HHVM warmup requests & docs?

jazzdan commented 9 years ago

Hi @simoncast,

The article still contains the best distillation of how to get it set up.

Can you post the version of HHVM that you're using, along with all of the configuration files that you are passing to the server?

simoncast commented 9 years ago

Hi @jazzdan

Thanks for replying. We tried two different ways of doing it.

1st scenario: server.ini: hhvm.server.warmup_document = /mnt/html/example/bin/hhvm/warmup-requests.hdf

2nd scenario: server.ini: hhvm.server.warmup_document = /mnt/html/example/bin/hhvm/warmup.hdf

https://gist.github.com/simoncast/f5dcf3b989057cdee660 for the file.

Neither approaches called the file in question. From the etsy article they specify this method of calling

Server {
WarmupRequests {
* = /var/etsy/current/bin/hhvm/warmup.hdf
  }
}

But that looks like the old HDF config files. How do we specify the same thing in the ini files? If we need to use the HDF file, do we just create the file and put it in the config directory or do we have to include it in the ini file or something?

jazzdan commented 9 years ago

Hey @simoncast,

Sorry about the late reply. While many of the HDF configuration options have been ported to INI configuration options, some of the more obscure ones still have not. In order to use warmup requests you need to put the configuration options in HDF files, not INI files.

simoncast commented 9 years ago

@jazzdan ok we'lld try the HDF file approach. Do we have to name the file anything specific or just create a config.hdf file in the directory with the ini files?

simoncast commented 9 years ago

Hi @jazzdan we've created the HDF files but we can't seem to get the PHP file to be called during restart. Is there a specific setting in php.ini/server.ini needed? We are using 3.7.0

jazzdan commented 9 years ago

Hi @simoncast,

Let me describe exactly how we have this set up, hopefully we can identify where we're missing something in your configuration.

We have an hhvm.ini file that contains a lot of hhvm specific configuration settings. It, however, does not have any lines related to the WarmupDocument.

We also have a hhvm.hdf file that contains hhvm specific settings in the HDF format. This file does have lines related to the warmup document. For us the contents of that file currently look like this:

Log {
    Access {
        * {
            SymLink = /var/log/hhvm/access.log
            File = /var/log/hhvm/access.log-%Y-%m-%d
            Format = %{X-Forwarded-For}i %{True-Client-IP}i %l %u %t "%r" %>s %b "%{Referer}i" "%{User-Agent}i" %{etsy_shop_id}n %{PHPSESSID}C %{etsy_uaid}n %V %{etsy_ab_selections}n %{etsy_request_uuid}n %{etsy_user_id}n %{etsy_api_consumer_key}n %{etsy_api_method_name}n %{php_memory_usage_bytes}n %{php_time_microsec}n %D %{X-Secure}i %{etsy_request_locale}n %{etsy_page_type}n %{display_mode}n %{X-CDN-Provider}i %{php_utime_microsec}n %{php_stime_microsec}n %{AL}n %O %{etsy_parent_uuid}n %{etsy_root_uuid}n
        }
    }
}

Server {
        WarmupRequests {
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
            * = /var/etsy/yin/bin/hhvm/prod_yin_prewarm.hdf
            * = /var/etsy/yang/bin/hhvm/prod_yang_prewarm.hdf
        }
}

This file contains references to other hdf documents that we use to warmup HHVM. Let's take a look at one of these files:

cmd = 1
url = /var/etsy/yang/bin/hhvm/warmup.php
remote_host = 127.0.0.1
remote_port = 35100
headers {
  0 {
    name = Accept
    value = */*
  }
  1 {
    name = Host
    value = www.etsy.com
  }
  2 {
    name = User-Agent
    value = Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.46 Safari/535.11
  }
}

This tells HHVM to execute /var/etsy/yang/bin/hhvm/warmup.php on startup.

Does this square with what you're doing?

simoncast commented 9 years ago

Hi Dan, Thank you!

As a bit of background: we are using Symfony 2 as the basis of a API backend for various client based frontend (primarily at this point AngularJS).

So after a bit of playing around yesterday I've got the warmup.php file being called. However, it doesn't seem to be interacting with HHVM that is producing any JIT compilation.

Our warmup.php file is essentially trying to call the API endpoints using CURL (e.g. 127.0.0.1/[some url]). The output of CURL is connection refused at 127.0.0.1 on what ever port I've tried. My hypothesis is that is because HHVM is not actually listening on any port during the warmup phase. Is that correct?

Does it make more sense to call the frontend controller in this case?

jazzdan commented 9 years ago

@simoncast that's correct, HHVM isn't accepting any connections on ports until the warmup document is completed.

Instead of having a script that curls HHVM, you should just have a script that executes some important, often-called code in your application directly. I've never used symfony, but I imagine maybe instantiate a couple ORM models and controllers?

For example, our "warmup script" (/var/etsy/yang/bin/hhvm/warmup.php) looks kinda like this:

#!/usr/bin/php
<?php

require_once 'bootstrap.php;

$response = null;

$search_suggestion_input = new Api_Input();
$search_suggestion_input->loadInput(['query' => 'warmup']);

$get_listings_input = new Api_Input();
$get_listings_input->loadInput(['listing_id' => 150008123]);

Search_Suggestion::handle($search_suggestion_input, $response);
Listings_GetListingCards::handle($get_listings_input, $response);

This is because Search Suggestions and Listing Card are two of our most hit API endpoints, so we want to warmup with those and ensure that they are JIT'd.

jazzdan commented 9 years ago

Hey @simoncast, did this resolve your issue?

simoncast commented 9 years ago

@jazzdan yes I think I've got it working now. Out of curiosity how many times do you normally call the warmup requests? 12 or 24? Are there any settings in php.ini we should set to make sure the JIT is run enough times?

jazzdan commented 9 years ago

Hey @simoncast,

We just call them 12 times, and we haven't made any changes relating to the JIT in our INI files.

collinbarrett commented 8 years ago

@jazzdan I am not a php developer, but I am trying to implement this warmup feature for the WordPress sites I serve via HHVM. What might my warmup.php look like if I only want to prime generic WordPress pages rather than API calls? (i.e. the site's homepage and a handful of other top-hit pages) Thanks!

jazzdan commented 8 years ago

Hi @collinbarrett,

I'm not familiar with wordpress, sorry! You could just make it your WordPress installation's index.php though I imagine.

fredemmott commented 8 years ago

Look at your access logs, and try to make your warmup.php imitate the most popular requests that you're actually getting.

collinbarrett commented 8 years ago

@jazzdan and @fredemmott , thanks. I haven't had a chance to try it yet, but I'll let you know.