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

Performance - Remove unnecessary get_time() calls to reduce redundant get_last_order() requests on admin Subscriptions list table #789

Open
wants to merge 7 commits into
base: trunk
Choose a base branch
from

Conversation

james-allan
Copy link
Contributor

@james-allan james-allan commented Feb 20, 2025

Part of https://github.com/woocommerce/woocommerce-subscriptions/issues/4795

Description

This PR reduces the number of duplicate queries running on the WooCommerce → Subscriptions list table, decreasing them from 137 to 82. This PR focuses on one key function: get_date_column_content(). A subsequent PR will make further improvements.

  • Previously, this function called get_time() multiple times (up to 4 times). When rendering the Last Order Date column, each call triggered a get_related_orders() query, resulting in redundant database reads.
  • The changes in this PR minimize unnecessary get_time() calls when generating date columns.

How to test this PR

  1. Install Query Monitor.
  2. Go to WooCommerce → Subscriptions
  3. Open the Query Monitor window and go to Database Queries → Duplicate Queries
  4. Note the number of duplicate queries.
  5. Each subscription in the list table is causing 6 calls to get_related_order_metadata()

Screenshot 2025-02-19 at 3 29 56 pm
137 duplicate queries.

  1. Checkout this branch and repeat the steps above.
  2. The number of duplicate queries should drop by roughly 3 x the number of subscriptions you have in the list table.
    • eg with 20 subscriptions in the list table this should remove ~60 duplicates.
    • Note: numbers may vary based on the number of subscriptions with no dates in some columns.
  3. There should be no difference in content or functionality on the list table.

Product impact

  • Added changelog entry (or does not apply)
  • Will this PR affect WooCommerce Subscriptions? yes/no/tbc, add issue ref
  • Will this PR affect WooCommerce Payments? yes/no/tbc, add issue ref
  • Added deprecated functions, hooks or classes to the spreadsheet


$date_type = wcs_normalise_date_type_key( $date_type, true );
return $this->format_date_to_display( $timestamp_gmt, $date_type );
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change introduces a new function format_date_to_display(). Prior to this to display a date we'd call get_date_to_display( $date_type ); and it would need to fetch the timestamp.

In cases where we already have the timestamp, this would result in another get_time() call. This new function simply refactors out the formatting function of the original get_date_to_display() so if we have the timestamp, we can call format_date_to_display() instead.

@@ -1316,7 +1327,7 @@ public function get_date_to_display( $date_type = 'next_payment' ) {
// translators: placeholder is human time diff (e.g. "3 weeks")
$date_to_display = sprintf( __( '%s ago', 'woocommerce-subscriptions' ), human_time_diff( current_time( 'timestamp', true ), $timestamp_gmt ) );
} else {
$date_to_display = date_i18n( wc_date_format(), $this->get_time( $date_type, 'site' ) );
$date_to_display = date_i18n( wc_date_format(), $timestamp_gmt + wc_timezone_offset() );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change removes one of the get_time() calls. Given we have the timestamp in GMT, and we want the time in the site's timezone, we offset the GMT time by the timezone offset instead.

Copy link
Contributor

@mattallan mattallan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @james-allan for these improvements!

Old
116 duplicate queries

image

New
68 duplicate queries

image


Code changes look good. I tested my site in different +/- timezones mainly just to test the $timestamp_gmt + wc_timezone_offset() change introduced in this PR.

I also left a small whitespace commit and condition ordering for tiny performance, but apart from that this PR is good to go :)

$tooltip_message .= __( 'This date should be treated as an estimate only. The payment gateway for this subscription controls when payments are processed.</br>', 'woocommerce-subscriptions' );
$tooltip_classes .= ' wcs-offsite-renewal';
}
if ( $subscription->payment_method_supports( 'gateway_scheduled_payments' ) && ! $subscription->is_manual() && $subscription_is_active ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move the $subscription_is_active check first in this condition since it's already an established variable and may avoid us instantiating payment gateways and running gateway support checks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah good idea. While fixing this I actually noticed that both conditions start with $subscription_is_active can they could be consolidated. Then I realised that that the $tooltip_message only changes if the subscription is active and so the "active" check can be made a top level condition.

I've fixed that in 759e7e9

Copy link
Contributor

@mattallan mattallan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @james-allan, I've tested the latest changes and improvements and happy to get this merged!

Duplicate queries halved on my WooCommerce > Subscriptions with these changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants