Make WordPress Core

Opened 7 years ago

Closed 7 years ago

#9007 closed defect (bug) (fixed)

Poor get_category_children() performance; rewrite to use get_term_children()

Reported by: _timk Owned by: ryan
Milestone: 2.8 Priority: normal
Severity: normal Version: 2.7
Component: Taxonomy Keywords: has-patch get_category_children
Focuses: Cc:


I'm working on a WordPress site with a few thousand categories. The categories are structured a bit, with one master category, a few organizational subcategories, and then the bulk of the remaining categories under those.

I'm looking to get a list of children for one of the middle-tier categories. Running get_categories() with the 'child_of' parameter calls get_category_children(). This call hits the 30-second server time limit. Outside the web environment, get_category_children() takes around a minute and 40 seconds to build a list of 589 categories on a relatively powerful desktop PC.

I'll attach a revised, non-recursive implementation of get_category_children() that uses get_term_children() and runs several orders of magnitude faster than the original in my environment. It returns almost instantly.

Attachments (2)

category-template.diff (1.2 KB) - added by _timk 7 years ago.
Patch: rewritten get_category_children() using get_term_children()
deprecate_get_category_children.9007.diff (2.5 KB) - added by filosofo 7 years ago.
Deprecate get_category_children. Really, how often do you need a string of concatenated category children ids?

Download all attachments as: .zip

Change History (10)

7 years ago

Patch: rewritten get_category_children() using get_term_children()

#1 @_timk
7 years ago

I re-ran the tests and came up with rough (time- and microtime-measured) execution times of 87 seconds and 0.00099 seconds for the original and revised implementations, respectively.

Improvement of almost 5 orders of magnitude for my case, extracting just under 600 child categories from a total of 1500+ in the database.

#2 @_timk
7 years ago

  • Component changed from General to Template

#3 @DD32
7 years ago

  • Component changed from Template to Taxonomy
  • Owner changed from anonymous to ryan

#4 @filosofo
7 years ago

  • Keywords has-patch get_category_children added

_timk, thanks for bringing this old function to light, but there are some odd things here.

  • You say that your problems stemmed from get_categories's calling get_category_children, but get_categories has never used get_category_children. Up to version 2.3 of WordPress, get_categories did use the private function _get_cat_children, but that was dropped in 2.3 with the implementation of the new taxonomy system.
  • Since WordPress 2.3 no core functions have called get_category_children. It's basically a vestige from the 2.2 and earlier days when it was used to build category queries.
  • get_category_children, having been used originally in core to build category queries, would have been better off as a private function, IMO.
  • get_category_children is not used in core, and my grep of the plugins repository turns up its use in only 5 plugins. Of those plugins, 3 seem to have been abandoned, as they're using the old 2.2 category tables. The other 2 say "tested up to 2.5.1"
  • So I think we should deprecate get_category_children. My patch does that.
  • _timk, if you're having performance issues in WordPress 2.7 or trunk, it's probably due to something else---let's try to figure out what that is.

7 years ago

Deprecate get_category_children. Really, how often do you need a string of concatenated category children ids?

#5 @_timk
7 years ago

You're right, of course; my apologies. I somehow managed to misread both the xdebug call trace and a quick grep through the tree to make sure the function wasn't an orphan. It turns out the function was being called directly on a portion of the site under someone else's control.

I support deprecation. When I first encountered the function, I actually expected it to behave like get_term_children(), returning an array of category IDs or objects.

#6 @_timk
7 years ago

Just discovered that get_category_children() was used because it's in an example in the documentation for in_category().

#7 @filosofo
7 years ago

I changed the wiki example you linked to to use get_term_children

#8 @ryan
7 years ago

  • Resolution set to fixed
  • Status changed from new to closed

(In [10703]) Deprecate get_category_children(). Props filosofo. fixes #9007

Note: See TracTickets for help on using tickets.