Support » Plugins » Hacks » Save a full second on cron execution

  • I found a problem with the cron mechanism and fixed it, saving 1 second per cron execution:

    WordPress’ internal cron mechanism relies on users accessing the page which internally triggers a new http request to cron.php. To avoid slowing down the user’s request, the cron request times out after 0.01 seconds (10 milliseconds) while the cron.php execution continues running in the background until it is finished. So far so good.

    However, the http request defaults to the cURL library (if installed) which is not capable of handling fractions of a second for timeouts until version 7.15.5. Therefore, the class WP_Http_Curl adjusts the fractional timeout to one full second (even if cURL would support it).

    class-http.php:1318:

    /*
    * CURLOPT_TIMEOUT and CURLOPT_CONNECTTIMEOUT expect integers. Have to use ceil since.
    * a value of 0 will allow an unlimited timeout.
    */
    $timeout = (int) ceil( $r['timeout'] );

    As a result, every cron execution is slowing down the user for at least 1 second. For sites with a lot of cron activity (like mine where Rankie checks a keyword rank every 2 minutes) this is quite significant, and can be actually measured pretty precisely.

    Luckily, WordPress also supports the stream transport library, which has no such limitations, so I decided to use it in favor of cURL for all requests that are non-blocking or have a fractional timeout. Here is my fix:

    class-http.php:303:

    // cURL cannot do real non-blocking calls, and the fractional timeout values are only
    // supported since cURL 7.15.5 but are not supported in WP_Http_Curl. So if one of these
    // conditions are met, we rather use PHP Streams to not delay the execution here (e.g. by cron).
    if ($args['blocking'] == false || ceil($args['timeout']) != $args['timeout']) {
      $available_transports = array( 'streams' );
    } else {
      $available_transports = array( 'curl', 'streams' );
    }

    class-http.php:323:

    $request_order = apply_filters( 'http_api_transports', $available_transports, $args, $url );

    Maybe this should be solved differently in the core at some point, but for now this is my fix, which works good for me. Thought I share it with you guys… 😉

    Regards,
    Bella

Viewing 1 replies (of 1 total)
Viewing 1 replies (of 1 total)
  • The topic ‘Save a full second on cron execution’ is closed to new replies.