14

The WordPress Heartbeat API uses admin-ajax.php to run AJAX calls. If User X leaves their browser open, many calls will be made to the server, with each call happening when there is a 'beat'. Now if User Y leaves their browser open, many more calls will be made to the server, with each of these calls happening when there is a 'beat'. It's possible a large website will also have User A, User B and User C all do the same.

My question:

Considering lots of users might access a website simultaneously, are WordPress Heartbeat API 'beats' staggered (the 'beat' for User X happens a few seconds before the 'beat' for User Y) or does a 'beat' occur at exactly the same time for all users?

If 'beats' aren't staggered, my concern is a very heavy load on the server at the point when a 'beat' occurs.

  • I don't know the answer to this, it is interesting though. I imagine you could do a basic test by logging into the admin area from multiple browsers/computers and than taking a closer look at the heartbeat requests and the according PHP script executions, somewhat like mentioned in this article. – Nicolai Sep 1 '14 at 8:29
  • @ialocin I activated a tick logger few days ago to check this out, but I then forgot to turn it off so when I checked it out today, the amount of ticks was quite scary ;-) – birgire Sep 1 '14 at 11:49
  • I can imagine that they accumulating quickly. The example from you answer gives a good idea I guess.. @birgire – Nicolai Sep 1 '14 at 13:16
7
+50

I would think the beats are Staggered by nature, becasue the next tick is determined by the browser time time() within the scheduleNextTick() method in the /wp-includes/js/heartbeat.jsfile:

 var delta = time() - settings.lastTick,
     interval = settings.mainInterval;

where it's used to schedule the next tick with the setTimeout function:

if ( delta < interval ) {
    settings.beatTimer = window.setTimeout(
        function() {
            connect();
        },
        interval - delta
     );
} else {
    connect();
}

The browser time is defined as:

function time() {
   return (new Date()).getTime();
}

The connect() method contains the ajax call and uses always()

.always( function() {
    settings.connecting = false;
    scheduleNextTick();
})

to schedule the next tick.

The available tick intervals are 5s, 15s, 30s and 60s.

For a large number of very active users, with a short tick interval, the beats might seem to happen simultaneously.

It's always good to have some data, so you could log the ticks from the logged in users, with the heartbeat_tick hook:

add_action( 'heartbeat_tick', 
    function(  $response, $screen_id  )
    {
        $file =  WP_CONTENT_DIR . '/ticks.log'; // Edit this filepath to your needs.

        if( file_exists( $file ) && is_writeable( $file ) ) 
        {
            file_put_contents( 
                $file, 
                sprintf( "%s - Tick from user_id : %d - from screen_id : %s" . PHP_EOL,
                    date( 'c' ),
                    get_current_user_id(),
                    $screen_id
                ), 
                FILE_APPEND | LOCK_EX 
            );
        }
    }
, 11, 2 ); 

Here's an example from the ticks.log file:

2014-09-01T12:41:04+00:00 - Tick from user_id : 1 - from screen_id : edit-post
2014-09-01T12:41:19+00:00 - Tick from user_id : 1 - from screen_id : edit-post
2014-09-01T12:41:34+00:00 - Tick from user_id : 1 - from screen_id : edit-post
2014-09-01T12:41:56+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:42:11+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:42:20+00:00 - Tick from user_id : 3 - from screen_id : upload
2014-09-01T12:42:38+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:43:05+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:43:08+00:00 - Tick from user_id : 3 - from screen_id : attachment
2014-09-01T12:43:20+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:43:36+00:00 - Tick from user_id : 1 - from screen_id : post
2014-09-01T12:44:17+00:00 - Tick from user_id : 3 - from screen_id : profile
  • Thanks for such a detailed answer. My understanding is there are two beats to a cycle. The initial beat which is determined by the browser and then a return beat. It's clear from your answer that the initial beat is staggered. Is the return beat (which sends data from the server back to the browser) staggered also? – henrywright Sep 2 '14 at 11:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.