Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Common performance improvements #1253

Merged
merged 47 commits into from Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6ec7322
Common performance improvements
borkweb Jan 9, 2020
816a934
Allow for cached output of templates before rendering and cache time …
borkweb Jan 9, 2020
4a91cc1
Pre HTML runs in the correct place, after file exists is done.
bordoni Jan 9, 2020
43c3fb7
Listen for more triggers for caching and support multiple triggers
borkweb Jan 9, 2020
6c865a3
Add transient purging and force a tribe_ prefix on long cache IDs
borkweb Jan 10, 2020
307a616
Cache countries fetch
borkweb Jan 10, 2020
d1047ea
Cache is_valid_date and get_week_start_end
borkweb Jan 10, 2020
e39c9f0
Improvements to performance around Tribe Assets
bordoni Jan 10, 2020
0a8a3f3
Merge branch 'fix/TEC-3130-performance-improvements-round-2' of githu…
bordoni Jan 10, 2020
d7e8240
Use memory cache for Tribe options
bordoni Jan 10, 2020
c768a39
In-memory cache last_occurrence
borkweb Jan 10, 2020
1e759d6
Improve performance Minified Files lookup
bordoni Jan 10, 2020
deded45
Merge branch 'fix/TEC-3130-performance-improvements-round-2' of githu…
bordoni Jan 10, 2020
9a98353
Fix arrayAccess OffsetExists implementation, it was the triggers fail…
bordoni Jan 11, 2020
c003bda
Try to fix the tests for Async.
bordoni Jan 11, 2020
61a844b
Last try to fix async delete.
bordoni Jan 11, 2020
7794bcc
tests are passing locally...
bordoni Jan 11, 2020
eb58fa0
Does this work?
bordoni Jan 11, 2020
a56e20b
?? Maybe now ??
bordoni Jan 11, 2020
cf6deff
Revert to original code.
bordoni Jan 11, 2020
e9ee285
Skip because there isn't a reason for this madness.
bordoni Jan 11, 2020
c90104d
It had passed
bordoni Jan 11, 2020
0ce98d9
False positive... It still needs to be skipped.
bordoni Jan 11, 2020
4108803
Make performance improvements to Canonical URL calls
bordoni Jan 12, 2020
14e93f5
Switch static to tribe_set/get_var so we can clear values in tests
borkweb Jan 12, 2020
5c2ab69
Remove debug
borkweb Jan 12, 2020
68401ef
Cache tribe_get_end_date
borkweb Jan 12, 2020
1db2529
Set cache in tribe_set_var rather than static class property
borkweb Jan 12, 2020
cfe19cb
Include methods for Unseting and checking if variables are set
bordoni Jan 12, 2020
27ef8cb
Merge branch 'fix/TEC-3130-performance-improvements-round-2' of githu…
bordoni Jan 12, 2020
a9cefe3
The answer fromt his method doesnt metter, so try/catch
bordoni Jan 12, 2020
bc1722b
Sanatize Title back in the mix for Assets class
bordoni Jan 12, 2020
fcf425c
Proper expiration for Week start/end and Settings caching
bordoni Jan 12, 2020
cd0542d
Add the ability to filter the offset before dynamically calculating it
borkweb Jan 13, 2020
1bc5c00
Update src/Tribe/Utils/Post_Thumbnail.php
borkweb Jan 13, 2020
fb7f5e7
Fix typo on test skipping message.
bordoni Jan 13, 2020
9aead84
Country caching
borkweb Jan 13, 2020
debadb0
Update src/Tribe/Date_Utils.php
borkweb Jan 13, 2020
04e47d7
Addressing code review
borkweb Jan 13, 2020
fc120d6
Merge branch 'fix/TEC-3130-performance-improvements-round-2' of githu…
borkweb Jan 13, 2020
9957ba7
Add @since
borkweb Jan 13, 2020
d5f6525
Update src/Tribe/Cache_Listener.php
borkweb Jan 13, 2020
9790734
Update src/Tribe/Container.php
borkweb Jan 13, 2020
468679a
Update src/Tribe/Container.php
borkweb Jan 13, 2020
c2202b2
Update src/Tribe/Repository.php
borkweb Jan 13, 2020
bc6a548
Remove duplicated line
borkweb Jan 13, 2020
56a0fe4
Merge branch 'fix/TEC-3130-performance-improvements-round-2' of githu…
borkweb Jan 13, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 37 additions & 30 deletions src/Tribe/Assets.php
Expand Up @@ -56,7 +56,10 @@ public function register_in_wp( $assets = null ) {
$assets = [ $assets ];
}

uasort( $assets, [ $this, 'order_by_priority' ] );
// Sorts by priority.
uasort( $this->assets, static function( $a, $b ) {
return (int) $a->priority === (int) $b->priority ? 0 : (int) $a->priority > (int) $b->priority;
} );

foreach ( $assets as $asset ) {
// Asset is already registered.
Expand Down Expand Up @@ -274,26 +277,49 @@ public function enqueue( $forcibly_enqueue = null ) {
* @return string|false The url to the minified version or false, if file not found.
*/
public static function maybe_get_min_file( $url ) {
$urls = [];
$wpmu_plugin_url = set_url_scheme( WPMU_PLUGIN_URL );
$wp_plugin_url = set_url_scheme( WP_PLUGIN_URL );
$wp_content_url = set_url_scheme( WP_CONTENT_URL );
$plugins_url = plugins_url();
static $wpmu_plugin_url;
sc0ttkclark marked this conversation as resolved.
Show resolved Hide resolved
static $wp_plugin_url;
static $wp_content_url;
static $plugins_url;
static $base_dirs;

$urls = [];
if ( ! isset( $wpmu_plugin_url ) ) {
$wpmu_plugin_url = set_url_scheme( WPMU_PLUGIN_URL );
}

if ( ! isset( $wp_plugin_url ) ) {
$wp_plugin_url = set_url_scheme( WP_PLUGIN_URL );
}

if ( ! isset( $wp_content_url ) ) {
$wp_content_url = set_url_scheme( WP_CONTENT_URL );
}

if ( ! isset( $plugins_url ) ) {
$plugins_url = plugins_url();
}

if ( ! isset( $base_dirs ) ) {
$base_dirs[ WPMU_PLUGIN_DIR ] = wp_normalize_path( WPMU_PLUGIN_DIR );
$base_dirs[ WP_PLUGIN_DIR ] = wp_normalize_path( WP_PLUGIN_DIR );
$base_dirs[ WP_CONTENT_DIR ] = wp_normalize_path( WP_CONTENT_DIR );
}

if ( 0 === strpos( $url, $wpmu_plugin_url ) ) {
// URL inside WPMU plugin dir.
$base_dir = wp_normalize_path( WPMU_PLUGIN_DIR );
$base_dir = $base_dirs[ WPMU_PLUGIN_DIR ];
$base_url = $wpmu_plugin_url;
} elseif ( 0 === strpos( $url, $wp_plugin_url ) ) {
// URL inside WP plugin dir.
$base_dir = wp_normalize_path( WP_PLUGIN_DIR );
$base_dir = $base_dirs[ WP_PLUGIN_DIR ];
$base_url = $wp_plugin_url;
} elseif ( 0 === strpos( $url, $wp_content_url ) ) {
// URL inside WP content dir.
$base_dir = wp_normalize_path( WP_CONTENT_DIR );
$base_dir = $base_dirs[ WP_CONTENT_DIR ];
$base_url = $wp_content_url;
} elseif ( 0 === strpos( $url, $plugins_url ) ) {
$base_dir = wp_normalize_path( WP_PLUGIN_DIR );
$base_dir = $base_dirs[ WP_PLUGIN_DIR ];
$base_url = $plugins_url;
} else {
// Resource needs to be inside wp-content or a plugins dir.
Expand All @@ -320,7 +346,7 @@ public static function maybe_get_min_file( $url ) {
// Check for all Urls added to the array.
foreach ( $urls as $partial_path ) {
$file_path = wp_normalize_path( $base_dir . $partial_path );
sc0ttkclark marked this conversation as resolved.
Show resolved Hide resolved
$file_url = plugins_url( basename( $file_path ), $file_path );
$file_url = $base_url . $partial_path;

if ( file_exists( $file_path ) ) {
return $file_url;
Expand Down Expand Up @@ -514,9 +540,6 @@ public function register( $origin, $slug, $file, $deps = [], $action = null, $ar
// Set the Asset on the array of notices.
$this->assets[ $slug ] = $asset;

// Sorts by priority.
uasort( $this->assets, [ $this, 'order_by_priority' ] );

// Return the Slug because it might be modified.
return $asset;
}
Expand Down Expand Up @@ -585,8 +608,6 @@ public function remove( $slug ) {
* it was not in the array of objects.
*/
public function get( $slug = null ) {
uasort( $this->assets, [ $this, 'order_by_priority' ] );

if ( is_null( $slug ) ) {
return $this->assets;
}
Expand All @@ -601,20 +622,6 @@ public function get( $slug = null ) {
return null;
}

/**
* Add the Priority ordering, which was causing an issue of not respecting which order stuff was registered.
*
* @since 4.7
*
* @param object $a First Subject to compare.
* @param object $b Second subject to compare.
*
* @return boolean
*/
public function order_by_priority( $a, $b ) {
return (int) $a->priority === (int) $b->priority ? 0 : (int) $a->priority > (int) $b->priority;
}

/**
* Checks if an Asset exists.
*
Expand Down
136 changes: 110 additions & 26 deletions src/Tribe/Cache.php
Expand Up @@ -10,6 +10,7 @@
* When used in its ArrayAccess API the cache will provide non persistent storage.
*/
class Tribe__Cache implements ArrayAccess {
const SCHEDULED_EVENT_DELETE_TRANSIENT = 'tribe_schedule_transient_purge';
const NO_EXPIRATION = 0;
const NON_PERSISTENT = - 1;

Expand All @@ -18,15 +19,28 @@ class Tribe__Cache implements ArrayAccess {
*/
protected $non_persistent_keys = array();

/**
* Bootstrap hook
borkweb marked this conversation as resolved.
Show resolved Hide resolved
*
* @since 5.0.0
*/
public function hook() {
if ( ! wp_next_scheduled( self::SCHEDULED_EVENT_DELETE_TRANSIENT ) ) {
wp_schedule_event( time(), 'twicedaily', self::SCHEDULED_EVENT_DELETE_TRANSIENT );
}

add_action( self::SCHEDULED_EVENT_DELETE_TRANSIENT, [ $this, 'delete_expired_transients' ] );
}

public static function setup() {
wp_cache_add_non_persistent_groups( array( 'tribe-events-non-persistent' ) );
}

/**
* @param string $id
* @param mixed $value
* @param int $expiration
* @param string $expiration_trigger
* @param string $id
* @param mixed $value
* @param int $expiration
* @param string|array $expiration_trigger
*
* @return bool
*/
Expand All @@ -37,11 +51,11 @@ public function set( $id, $value, $expiration = 0, $expiration_trigger = '' ) {
* Filters the expiration for cache objects to provide the ability
* to make non-persistent objects be treated as persistent.
*
* @param int $expiration Cache expiration time.
* @param string $id Cache ID.
* @param mixed $value Cache value.
* @param string $expiration_trigger Action that triggers automatic expiration.
* @param string $key Unique cache key based on Cache ID and expiration trigger last run time.
* @param int $expiration Cache expiration time.
* @param string $id Cache ID.
* @param mixed $value Cache value.
* @param string|array $expiration_trigger Action that triggers automatic expiration.
* @param string $key Unique cache key based on Cache ID and expiration trigger last run time.
*
* @since 4.8
*/
Expand All @@ -61,10 +75,10 @@ public function set( $id, $value, $expiration = 0, $expiration_trigger = '' ) {
}

/**
* @param $id
* @param $value
* @param int $expiration
* @param string $expiration_trigger
* @param $id
* @param $value
* @param int $expiration
* @param string|array $expiration_trigger
*
* @return bool
*/
Expand All @@ -77,11 +91,11 @@ public function set_transient( $id, $value, $expiration = 0, $expiration_trigger
*
* Note: When a default value or callback is specified, this value gets set in the cache.
*
* @param string $id The key for the cached value.
* @param string $expiration_trigger Optional. Hook to trigger cache invalidation.
* @param mixed $default Optional. A default value or callback that returns a default value.
* @param int $expiration Optional. When the default value expires, if it gets set.
* @param mixed $args Optional. Args passed to callback.
* @param string $id The key for the cached value.
* @param string|array $expiration_trigger Optional. Hook to trigger cache invalidation.
* @param mixed $default Optional. A default value or callback that returns a default value.
* @param int $expiration Optional. When the default value expires, if it gets set.
* @param mixed $args Optional. Args passed to callback.
*
* @return mixed
*/
Expand Down Expand Up @@ -112,7 +126,7 @@ public function get( $id, $expiration_trigger = '', $default = false, $expiratio

/**
* @param string $id
* @param string $expiration_trigger
* @param string|array $expiration_trigger
*
* @return mixed
*/
Expand All @@ -122,7 +136,7 @@ public function get_transient( $id, $expiration_trigger = '' ) {

/**
* @param string $id
* @param string $expiration_trigger
* @param string|array $expiration_trigger
*
* @return bool
*/
Expand All @@ -132,25 +146,73 @@ public function delete( $id, $expiration_trigger = '' ) {

/**
* @param string $id
* @param string $expiration_trigger
* @param string|array $expiration_trigger
*
* @return bool
*/
public function delete_transient( $id, $expiration_trigger = '' ) {
return delete_transient( $this->get_id( $id, $expiration_trigger ) );
}

/**
* Purge all expired tribe_ transients.
*
* This uses a modification of the the query from https://core.trac.wordpress.org/ticket/20316
borkweb marked this conversation as resolved.
Show resolved Hide resolved
*
* @since 5.0.0
*/
public function delete_expired_transients() {
global $wpdb;

$time = time();

$sql = "
DELETE
a,
b
FROM
{$wpdb->options} a
INNER JOIN {$wpdb->options} b
ON b.option_name = CONCAT( '_transient_timeout_tribe_', SUBSTRING( a.option_name, 12 ) )
AND b.option_value < {$time}
WHERE
a.option_name LIKE '\_transient_tribe\_%'
AND a.option_name NOT LIKE '\_transient\_timeout_tribe\_%'
";
$wpdb->query( $sql );
}

/**
* @param string $key
* @param string $expiration_trigger
* @param string|array $expiration_trigger
*
* @return string
*/
public function get_id( $key, $expiration_trigger = '' ) {
$last = empty( $expiration_trigger ) ? '' : $this->get_last_occurrence( $expiration_trigger );
if ( is_array( $expiration_trigger ) ) {
$triggers = $expiration_trigger;
} else {
$triggers = array_filter( explode( '|', $expiration_trigger ) );
}

$last = 0;
foreach ( $triggers as $trigger ) {
// Bail on empty trigger otherwise it creates a `tribe_last_` opt on the DB.
if ( empty( $trigger ) ) {
continue;
}

$occurrence = $this->get_last_occurrence( $trigger );

if ( $occurrence > $last ) {
$last = $occurrence;
}
}

$last = empty( $last ) ? '' : $last;
$id = $key . $last;
if ( strlen( $id ) > 40 ) {
$id = md5( $id );
if ( strlen( $id ) > 80 ) {
$id = 'tribe_' . md5( $id );
}

return $id;
Expand All @@ -166,7 +228,27 @@ public function get_id( $key, $expiration_trigger = '' ) {
* @return float The time (microtime) an action last occurred, or the current microtime if it never occurred.
*/
public function get_last_occurrence( $action ) {
return (float) get_option( 'tribe_last_' . $action, microtime( true ) );
static $cache_var_name = __METHOD__;

$cache_last_actions = tribe_get_var( $cache_var_name, [] );

if ( isset( $cache_last_actions[ $action ] ) ) {
return $cache_last_actions[ $action ];
}

$last_action = (float) get_option( 'tribe_last_' . $action, null );

if ( ! $last_action ) {
$last_action = microtime( true );

update_option( 'tribe_last_' . $action, $last_action );
}

$cache_last_actions[ $action ] = (float) $last_action;

tribe_set_var( $cache_var_name, $cache_last_actions );

return $cache_last_actions[ $action ];
}

/**
Expand All @@ -182,6 +264,8 @@ public function set_last_occurrence( $action, $timestamp = 0 ) {
$timestamp = microtime( true );
}
update_option( 'tribe_last_' . $action, (float) $timestamp );

$this->delete_expired_transients();
}

/**
Expand Down