Users: Introduce the concept of a large site in order to speed up the Users screen when there are many users.

Calling the `count_users()` function is expensive, regardless of the counting strategy that's used, and it gets
slower the more users there are on a site. In order to speed up the Users screen in the admin area, calling
`count_users()` can be avoided entirely while still displaying the total count for users.

This introduces some new functions:

* `wp_is_large_user_count()`
* `wp_get_active_user_count()`
* `wp_update_active_user_count()`

A corresponding `wp_is_large_user_count` filter is also introduced.

Props tharsheblows, johnbillion

Fixes #38741

Built from https://develop.svn.wordpress.org/trunk@41613


git-svn-id: http://core.svn.wordpress.org/trunk@41448 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
John Blackbourn 2017-09-27 13:04:47 +00:00
parent 0fe4c3b3f2
commit 807bc5a6c9
6 changed files with 114 additions and 18 deletions

View File

@ -166,27 +166,48 @@ class WP_Users_List_Table extends WP_List_Table {
global $role; global $role;
$wp_roles = wp_roles(); $wp_roles = wp_roles();
$count_users = true;
if ( wp_is_large_user_count() ) {
$count_users = false;
} elseif ( is_multisite() && wp_is_large_network( 'users' ) ) {
$count_users = false;
}
if ( $this->is_site_users ) { if ( $this->is_site_users ) {
$url = 'site-users.php?id=' . $this->site_id; $url = 'site-users.php?id=' . $this->site_id;
switch_to_blog( $this->site_id ); if ( $count_users ) {
$users_of_blog = count_users( 'time', $this->site_id ); switch_to_blog( $this->site_id );
restore_current_blog(); $users_of_blog = count_users( 'time', $this->site_id );
restore_current_blog();
}
} else { } else {
$url = 'users.php'; $url = 'users.php';
$users_of_blog = count_users(); if ( $count_users ) {
$users_of_blog = count_users();
}
} }
$total_users = $users_of_blog['total_users']; if ( $count_users ) {
$avail_roles =& $users_of_blog['avail_roles']; $total_users = $users_of_blog['total_users'];
unset($users_of_blog); $avail_roles =& $users_of_blog['avail_roles'];
unset($users_of_blog);
} else {
$avail_roles = array();
}
$class = empty($role) ? ' class="current"' : ''; $class = empty($role) ? ' class="current"' : '';
$role_links = array(); $role_links = array();
$role_links['all'] = "<a href='$url'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '</a>';
if ( $count_users ) {
$role_links['all'] = "<a href='$url'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '</a>';
} else {
$role_links['all'] = "<a href='$url'$class>" . _x( 'All', 'users' ) . '</a>';
}
foreach ( $wp_roles->get_names() as $this_role => $name ) { foreach ( $wp_roles->get_names() as $this_role => $name ) {
if ( !isset($avail_roles[$this_role]) ) if ( $count_users && !isset($avail_roles[$this_role]) ) {
continue; continue;
}
$class = ''; $class = '';
@ -195,12 +216,14 @@ class WP_Users_List_Table extends WP_List_Table {
} }
$name = translate_user_role( $name ); $name = translate_user_role( $name );
/* translators: User role name with count */ if ( $count_users ) {
$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles[$this_role] ) ); /* translators: User role name with count */
$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles[$this_role] ) );
}
$role_links[$this_role] = "<a href='" . esc_url( add_query_arg( 'role', $this_role, $url ) ) . "'$class>$name</a>"; $role_links[$this_role] = "<a href='" . esc_url( add_query_arg( 'role', $this_role, $url ) ) . "'$class>$name</a>";
} }
if ( ! empty( $avail_roles['none' ] ) ) { if ( ! $count_users || ! empty( $avail_roles['none' ] ) ) {
$class = ''; $class = '';
@ -209,8 +232,10 @@ class WP_Users_List_Table extends WP_List_Table {
} }
$name = __( 'No role' ); $name = __( 'No role' );
/* translators: User role name with count */ if ( $count_users ) {
$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles['none' ] ) ); /* translators: User role name with count */
$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles['none' ] ) );
}
$role_links['none'] = "<a href='" . esc_url( add_query_arg( 'role', 'none', $url ) ) . "'$class>$name</a>"; $role_links['none'] = "<a href='" . esc_url( add_query_arg( 'role', 'none', $url ) ) . "'$class>$name</a>";
} }

View File

@ -466,6 +466,11 @@ add_filter( 'nav_menu_item_id', '_nav_menu_item_id_use_once', 10, 2 );
// Widgets // Widgets
add_action( 'init', 'wp_widgets_init', 1 ); add_action( 'init', 'wp_widgets_init', 1 );
// User counts
foreach ( array( 'user_register', 'deleted_user' ) as $action ){
add_action( $action, 'wp_update_active_user_count' );
}
// Admin Bar // Admin Bar
// Don't remove. Wrong way to disable. // Don't remove. Wrong way to disable.
add_action( 'template_redirect', '_wp_admin_bar_init', 0 ); add_action( 'template_redirect', '_wp_admin_bar_init', 0 );

View File

@ -5833,3 +5833,65 @@ All at ###SITENAME###
$site_name $site_name
), $email_change_email['message'], $email_change_email['headers'] ); ), $email_change_email['message'], $email_change_email['headers'] );
} }
/**
* Whether or not we have a large site, based on its number of users.
*
* The default criteria for a large site is more than 10,000 users.
*
* @since 4.9.0
*
* @return bool True if the site meets the criteria for large. False otherwise.
*/
function wp_is_large_user_count() {
$count = wp_get_active_user_count();
/**
* Filters whether the site is considered large, based on its number of users.
*
* The default criteria for a large site is more than 10,000 users.
*
* @since 4.9.0
*
* @param bool $is_large_user_count Whether the site is considered large.
* @param int $count The number of users on the site.
*/
return apply_filters( 'wp_is_large_user_count', $count > 10000, $count );
}
/**
* Update the active user count.
*
* @since 4.9.0
* @global wpdb $wpdb WordPress database abstraction object.
*
* @return int The active user count.
*/
function wp_update_active_user_count() {
global $wpdb;
$count = $wpdb->get_var( "
SELECT COUNT(ID) as c
FROM {$wpdb->users}
" );
$count=12345;
update_option( 'active_user_count', $count );
return (int) $count;
}
/**
* The number of active users.
*
* @since 4.9.0
*
* @return int The active user count.
*/
function wp_get_active_user_count() {
$count = get_option( 'active_user_count', false );
if ( false === $count ) {
$count = wp_update_active_user_count();
}
return (int) $count;
}

View File

@ -2553,6 +2553,11 @@ function wp_is_large_network( $using = 'sites', $network_id = null ) {
if ( 'users' == $using ) { if ( 'users' == $using ) {
$count = get_user_count( $network_id ); $count = get_user_count( $network_id );
$is_large = ( $count > 10000 );
/** This filter is documented in wp-includes/functions.php */
$is_large = apply_filters( 'wp_is_large_user_count', $is_large, $count );
/** /**
* Filters whether the network is considered large. * Filters whether the network is considered large.
* *
@ -2564,7 +2569,7 @@ function wp_is_large_network( $using = 'sites', $network_id = null ) {
* @param int $count The count of items for the component. * @param int $count The count of items for the component.
* @param int $network_id The ID of the network being checked. * @param int $network_id The ID of the network being checked.
*/ */
return apply_filters( 'wp_is_large_network', $count > 10000, 'users', $count, $network_id ); return apply_filters( 'wp_is_large_network', $is_large, 'users', $count, $network_id );
} }
$count = get_blog_count( $network_id ); $count = get_blog_count( $network_id );

View File

@ -78,8 +78,7 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) {
$wp_install = network_site_url(); $wp_install = network_site_url();
$multisite_enabled = 1; $multisite_enabled = 1;
} else { } else {
$user_count = count_users(); $user_count = wp_get_active_user_count();
$user_count = $user_count['total_users'];
$multisite_enabled = 0; $multisite_enabled = 0;
$num_blogs = 1; $num_blogs = 1;
$wp_install = home_url( '/' ); $wp_install = home_url( '/' );

View File

@ -4,7 +4,7 @@
* *
* @global string $wp_version * @global string $wp_version
*/ */
$wp_version = '4.9-alpha-41612'; $wp_version = '4.9-alpha-41613';
/** /**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema. * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.