Maybe this is a support request because of my brain not working...

When taxonomy_get_tree() gets called it stores the tree in static vars for that page load, but if you programmatically create a term, say with drupal_execute(), then try to add a node to that term with drupal_execute() it will tell you you have selected an illegal choice. I've attached a patch to illustrate my point, but I'm sure it could get cleaned up.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

RobRoy’s picture

Title: Does taxonomy_get_tree() need a way to clear the static vars? » taxonomy_get_tree() needs a way to clear its static cache
Status: Needs review » Needs work

Sure of this now, better title.

Should the $reset just exit instead of processing the whole tree again?

I'm thinking this should probably get called on taxonomy_* API functions too because of...

taxonomy_get_tree(); // Build tree
taxonomy_save_term(); // Add new term
taxonomy_get_tree(); // Get tree again, but it doesn't have the new term.

Any other suggestions before I re-roll?

RobRoy’s picture

Version: 5.x-dev » 6.x-dev
Category: bug » feature
Status: Needs work » Needs review
FileSize
1.93 KB

Here is the code for D5 to cause this error. Say you wanted to create a forum container and then a child forum under that container in an install profile? Not too uncommon.

Do this and you'll get an "invalid choice selected" error from the last drupal_execute().

I guess this is a feature since you don't HAVE to use drupal_execute, so maybe for D6 we need to refactor since this patch feels a bit hackish. Could we use Drupal's caching mechanism to cache taxonomy? Then, we could do a cache_clear_all('vid:3', 'taxonomy') or whatever after modifying terms so the tree would be rebuilt.

I need some guidance from above here. ;)

// Create forum container.
  $form_values = array(
    'name' => 'Forum Container',
    'description' => "",
    'parent' => array(0 => 0),
    'vid' => 1,
  );
  drupal_execute('forum_form_container', $form_values);
  
  // Must reset static tree or else the following drupal_execute results in a
  // Invalid choice selected error. Really this reset would be done in
  // taxonomy_save_term() just showing here to illustrate the point.
  taxonomy_get_tree(NULL, NULL, NULL, NULL, TRUE);

  $container_tid = (int)db_result(db_query('SELECT MAX(tid) FROM {term_data}'));
  $form_values = array(
    'name' => 'General Discussion',
    'description' => "For any discussion that doesn't fit anywhere else.",
    'parent' => array(0 => $container_tid),
    'vid' => 1,
  );
  drupal_execute('forum_form_forum', $form_values);
RobRoy’s picture

Title: taxonomy_get_tree() needs a way to clear its static cache » Use Drupal caching mechanism for taxonomy_get_tree()
Status: Needs review » Needs work
FileSize
1.15 KB

Here's the start for a caching patch. I haven't really tested it, just wanted to get it up now while I remember. It should probably go in it's own cache_taxonomy, but I wanted a bit of direction before heading in that direction.

killes@www.drop.org’s picture

Just for the record: I don't think we need an extra table for cached taxonomies. The plain cache table contains only a single entry on a default Drupal install, there is plenty of space, especially for cached itesm that won't change that often.

RobRoy’s picture

Status: Needs work » Needs review
FileSize
3.69 KB

Okay, updated this. I'm stoked! This is a huge speed boost for sites with large taxonomies. There are a couple things to point out.

1. This only caches the tree when called directly and since there is recursion I had to add another param to not cache recursive calls.
2. Some int casting for the cache ID because I'm not sure where NULL or '' is passed in, should I cast to (string) so '' and 0 return different trees?
3. On term delete I added a forward-looking feature to clear caches where a term could have a child term in a different vocabulary. Not sure if any contrib modules do this, just to be safe.

Could use some testing, but seems to work fine so far. Maybe some benchmarks too?

killes@www.drop.org’s picture

Looks good, some benchmakrs would indeed be helpful.

RobRoy’s picture

Okay, I have a vocab with 509 terms and hierarchy built with devel. I did some super ghetto benchmarking using -c1 -n10 just to get an idea because running -c10 -n500 on the uncached tree was timing out!

It's pretty apparent that not generating the tree on each request is a huge speedup. I'll leave it to someone else to recommend or do a better benchmark than I have time for atm. I even left the query cache on. This is just of the taxonomy overview page and keep in mind this is on my bogged down laptop, but you should get the idea.

# ab -c1 -n10 http://local.drupalhead3.com/?q=admin/content/taxonomy/1

# HEAD without caching on taxonomy_get_tree()
Requests per second: 0.27 [#/sec] (mean)
Time per request: 3746.387 [ms] (mean)

# HEAD with caching on taxonomy_get_tree()
Requests per second: 4.42 [#/sec] (mean)
Time per request: 226.325 [ms] (mean)

RobRoy’s picture

Title: Use Drupal caching mechanism for taxonomy_get_tree() » Huge speedup! Use Drupal caching mechanism for taxonomy_get_tree()

Changed title to sell it more. :P

ChrisKennedy’s picture

Status: Needs review » Needs work

I created a vocabulary (page type, multiple hierarchy, related terms, no freetagging, multiple select, not required, 0 weight) and added a term, but "list terms" keeps showing "No terms available." and the terms aren't showing up as possible related terms or parent terms when I try to add another term.

If I then revert to HEAD the terms will show up. They are being inserted correctly but apparently the cache check isn't finding them.

RobRoy’s picture

Status: Needs work » Needs review
FileSize
3.43 KB

Okay, here is a re-roll just in case. The cache is clearing for me...hmmm.

RobRoy’s picture

FileSize
0 bytes

Okay, here is a re-roll just in case. The cache is clearing for me...hmmm.

RobRoy’s picture

#10 is the one. I was getting a 500 error on d.o so the last one didn't come through.

beginner’s picture

patch in #11 didn't upload.

If this issue is indeed a duplicate of http://drupal.org/node/83057 , then it is not a feature request but a bug.

beginner’s picture

never mind about patch in #11. I notice a bit late that it's a duplicate post of #10.

RobRoy’s picture

Title: Huge speedup! Use Drupal caching mechanism for taxonomy_get_tree() » Huge speedup! Use Drupal caching mechanism for taxonomy_get_tree() and fix a taxonomy bug and notices
FileSize
5.44 KB

Okay, revisited this patch and think I actually got it working this time. I guess I'm a little too late for D6 as this adds an optional parameter to taxonomy_get_tree() but I will leave for the powers that be. But this is a frickin huge speedup, did you see the title? :P

Also...
- Fixed a bug where vid was being passed to taxonomy_form_term() in taxonomy_admin_term_edit() making the parent dropdown not show. Should roll into another patch if this is postponed to D7.
- Some notices.

RobRoy’s picture

FileSize
5.49 KB

Re-roll from root folder. Oops.

RobRoy’s picture

Complimentary issue at http://drupal.org/node/146688 it seems.

Wim Leers’s picture

Subscribing.

Zothos’s picture

*Subscribing*

get in in dudes ^^

catch’s picture

Status: Needs review » Needs work

This needs a re-roll after the split patch went in.

Wim Leers’s picture

Status: Needs work » Needs review

Reroll. While this is an API change (an additional boolean $cache parameter in taxonomy_get_tree()), it doesn't break anything. So please don't make this patch wait for D7!

The changes in the admin area of the previous patch are no longer necessary, all of that is already fixed.

This is potentially a huge speed up for taxonomy browsers, and also for the Hierarchical Select module.

Wim Leers’s picture

FileSize
4.39 KB

Forgot the patch...

Wim Leers’s picture

Assigned: Unassigned » Wim Leers
Wim Leers’s picture

FileSize
3.91 KB

The previous patch included a change to index.php. Use this one instead.

Wim Leers’s picture

Title: Huge speedup! Use Drupal caching mechanism for taxonomy_get_tree() and fix a taxonomy bug and notices » [performance] DB caching for taxonomy_get_tree() and fix a taxonomy bug and notices

Better title.

catch’s picture

Well this applies cleanly, the only implementation in core that's obvious is the forum inde and that works fine with a couple of levels of hierarchy. Not sure how to go about testing the performance implication to actually get this RTBC though.

The index improvements are now over at: http://drupal.org/node/164532

Wim Leers’s picture

See RobRoy's tests in #7?

catch’s picture

Status: Needs review » Reviewed & tested by the community

Well in that case it's has had reviews by various people, it's a big boost, and it's a small API change. The main boost within core would be forum_get_forums, which is a very slow query. Patch applies cleanly and doesn't throw up any errors etc.

If the API bit stops it getting into D6, it's a decision for Goba and Dries to make, so bumping to their queue.

Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Needs work

I looked through the patch. Comments:

- having a specific cache_clear_all() before a generic one looked like interesting, but I see that the generic only clears cache_page and cache_block, so we need the specific clears still
- removing the array cast from taxonomy_del_term()s taxonomy_get_term() modifies the API for module_invoke_all('taxonomy', 'delete', 'term', $term) called later
- the caches seem to be very fine grained based on vid, parent tid, depth and max depth, which in combination could make up for a huge number of cached entries, which could easily clutter up the generic cache table (I know adding another cache table might be even more API change now)
- what testing is required still to clean up: "// Don't cache tree if empty, may be able to remove this after more testing."?

The benchmark looks impressive for sure, but there were changes in the code since then, so it should be rebenchmarked IMHO. Also I wonder what killes has to say about the current state of the code.

I am marking needs work because of the array cast API change. Others seem to need some discussion, but might not need code change.

Wim Leers’s picture

Version: 6.x-dev » 7.x-dev
Wim Leers’s picture

I walked into this bug again today. I'll reroll with Gábor's comments taken into account.

funana’s picture

Hi there,

could anybody give me a patch for Drupal 5.7? Or tell me which patch I can use?

Thank you!

aclight’s picture

Subscribing. The inability to reset the static cache in taxonomy_get_tree() makes it rather difficult for the drupal.org testing installation profile to create forums and containers via drupal_execute().

Xen’s picture

The static cache is also a problem for migration code that automatically creates terms and show a node edit form. If the pathauto module is active, its hook_taxonomy calls taxonomy_get_tree which caches the tree after the first term is added, and the rest doesn't show up in the node form. They do, however, get created.

doq’s picture

Subscribing.

lilou’s picture

Issue tags: +Performance

Add tag.

JeremyFrench’s picture

Subscribe.

JeremyFrench’s picture

I ran into this issue on D6, looking at the D7 code, this now uses drupal_static to declare the variables. So they can be cleared.

Should this ticket be put back to D6 where the issue persists?

catch’s picture

Category: feature » task

This is still a performance issue in HEAD and that was the main part of the patch IMO - maybe open a separate issue for D6 but reference this one for the $reset param.

JeremyFrench’s picture

I have hacked a D6 taxonomy module to do some caching and cache clears. I may see if I can port this to D7.

Personally I don't think that taxonomy_get_tree can scale as a function, if you have a very large vocabulary it takes an age just to deserialise the data. My preferred approach would be to only allow something like and Iterator, or dom like functions (get parents, get children, get next sibling) for taxonomies and terms, but I think that is probably too much of an API change at this stage.

Thoughts anyone?

catch’s picture

We can't change the API, at most tweaks. If there's something which helps some cases, that'd be great. We really need to work on pluggable systems, paging etc. in Drupal 8.

JeremyFrench’s picture

Assigned: Wim Leers » JeremyFrench
Status: Needs work » Needs review
FileSize
1.09 KB

This patch might do it. From a look at the code places which edit terms call cache_clear_all(). The unit tests pass locally.

JeremyFrench’s picture

Title: [performance] DB caching for taxonomy_get_tree() and fix a taxonomy bug and notices » [performance] DB caching for taxonomy_get_tree()

I have changed the title for clarity. I think the other issues raised in this ticket originally have been split out.

JeremyFrench’s picture

Assigned: JeremyFrench » Unassigned
c960657’s picture

Status: Needs review » Needs work
 function taxonomy_get_tree($vid, $parent = 0, $max_depth = NULL, $depth = -1) {
   $children = &drupal_static(__FUNCTION__, array());
   $parents = &drupal_static(__FUNCTION__ . 'parents', array());
   $terms = &drupal_static(__FUNCTION__ . 'terms', array());

   $depth++;
 
+  // If the function is being called with default arguments see if a
+  // cached copy exsists.
+  if ($parent == 0 && $max_depth == NULL && $depth == -1) {
+    if ($cached_tree = cache_get('taxonomy_get_tree_' . $vid)) {
+      return $cached_tree;
+    }
+  }  
   // We cache trees, so it's not CPU-intensive to call get_tree() on a term
   // and its children, too.
   if (!isset($children[$vid]))

$depth is never -1, because it was incremented three lines above. (BTW, unrelated to this issue, but wouldn't it be more intuitive to set the default value to 0, remove the $depth++, and then instead pass $depth + 1 in the recursive function call?).

You should return $cached_tree->data instead of the entire cache object, but ...

Instead of returning early, why not move the cache_get() into the if (!isset($children[$vid])) { block and then always fetch the cached value, even if $max_depth != NULL and $parent != 0. Then just put the cached value into $children[$vid][0] and let the rest of the function do its magic.

    cache_set('taxonomy_get_tree_' . $vid,$tree);

Missing space after comma.
I suggest using colon as separator before $vid in the cache cid. This pattern is used elsewhere in core.

I'm not sure why you removed the new cache_clear_all('taxonomy_get_tree_' . $vid, ...) calls? cache_clear_all() without arguments only clears cache_page and cache_block.

JeremyFrench’s picture

Thanks for the review, I'll try to get round to fixing. Most of the comments make sense, the only one that I would question is:
Instead of returning early, why not move the cache_get() into the if (!isset($children[$vid])) { block and then always fetch the cached value, even if $max_depth != NULL and $parent != 0. Then just put the cached value into $children[$vid][0] and let the rest of the function do its magic.
This would create a lot of cache keys for vocabs with a deep hierarchy. Many of these cache keys would only be set when taxonomy_get_tree calls itself. So would not give a performance gain.
Where as you get the biggest performance hit when querying the root of a vocabulary. So there would be a bigger cache for very little benefit most of the time.

Ideally you could set a flag to determine weather you are on a recursive call or calling the function from elsewhere and only cache on the non hierarchical calls. But this may require an API change so I went with the simpler option.

c960657’s picture

Ideally you could set a flag to determine weather you are on a recursive call or calling the function from elsewhere and only cache on the non hierarchical calls.

You can use $depth for that. However, on second thought I don't think my initial thought about always using the cache can be implemented as easy as described, but something can be done:

WRT to $max_depth you could get the cached copy of the whole tree and the prune it in PHP code without hitting the database.

Using the cached copy of the whole tree for $parent != 0 is a bit tougher, because there is no easy way to find the appropriate subtree in the array unless you also save the $parents array to the cache. With this you can find the path of parent tids on the way from the specified $parent to the root and then use that to descend down through the cached tree. I don't know how this will perform.

Mir’s picture

Status: Needs work » Needs review

#42: taxonomy_get_tree_cache.patch queued for re-testing.

janusman’s picture

Code seems fine, but it really seems to be a solution looking for a problem.

Would anyone care to comment why this is important? =)

JeremyFrench’s picture

With very large taxonomies, taxonomy_get_tree can become a bottleneck on quite a few pages. I think some of the other changes in D7 improve this, by not calling it so much.

It may be worth testing a D7 install with a 100,000 term vocabulary, to see how it performs.

slantview’s picture

Subscribing.

Gerhard Killesreiter’s picture

Status: Needs review » Needs work

setting to "needs work" since the concerns expressed in #45 haven't been addressed.

phantomvish’s picture

+1 subscribing

JeremyFrench’s picture

now that taxonomy_get_tree() memory issues is done, is there a genrall feeling as to whether this is needed any more.

JeremyFrench’s picture

Status: Needs work » Needs review
Issue tags: -Performance

#42: taxonomy_get_tree_cache.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, taxonomy_get_tree_cache.patch, failed testing.

vin247’s picture

Status: Needs work » Needs review

#42: taxonomy_get_tree_cache.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Performance

The last submitted patch, taxonomy_get_tree_cache.patch, failed testing.

catch’s picture

Version: 7.x-dev » 8.x-dev

Moving this to D8.

xjm’s picture

bailey86’s picture

Status: Needs work » Needs review

taxonomy.tree.patch queued for re-testing.

bailey86’s picture

So far this seems to be working for me:

function taxonomy_get_tree_with_reset($vid, $parent = 0, $depth = -1, $max_depth = NULL, $reset = FALSE) {
  static $children, $parents, $terms;

  if ($reset) {
    unset($children[$vid]);
    unset($parents[$vid]);
    unset($terms[$vid]);
  }


  $depth++;

  // We cache trees, so it's not CPU-intensive to call get_tree() on a term
  // and its children, too.
  if (!isset($children[$vid])) {
    $children[$vid] = array();

    $result = db_query(db_rewrite_sql('SELECT t.tid, t.*, parent FROM {term_data} t INNER JOIN {term_hierarchy} h ON t.tid = h.tid WHERE t.vid = %d ORDER BY weight, name', 't', 'tid'), $vid);
    while ($term = db_fetch_object($result)) {
      $children[$vid][$term->parent][] = $term->tid;
      $parents[$vid][$term->tid][] = $term->parent;
      $terms[$vid][$term->tid] = $term;
    }
  }

  $max_depth = (is_null($max_depth)) ? count($children[$vid]) : $max_depth;
  $tree = array();
  if ($max_depth > $depth && !empty($children[$vid][$parent])) {
    foreach ($children[$vid][$parent] as $child) {
      $term = drupal_clone($terms[$vid][$child]);
      $term->depth = $depth;
      // The "parent" attribute is not useful, as it would show one parent only.
      unset($term->parent);
      $term->parents = $parents[$vid][$child];
      $tree[] = $term;
      if (!empty($children[$vid][$child])) {
        $tree = array_merge($tree, taxonomy_get_tree_with_reset($vid, $child, $depth, $max_depth));
      }
    }
  }

  return $tree;
}
xjm’s picture

Status: Needs review » Needs work

There isn't a current patch in this issue.

bailey86’s picture

BTW - I'm not (yet) familiar with patching - so if someone could create a patch that would be great.

When I've created a patch for a project I'm working on I'll come back to this and create a patch if needed.

xjm’s picture

Regarding #64, check out:
http://drupal.org/patch
http://drupal.org/patch/create

It's not too complicated, I promise. :)

jibran’s picture

Title: [performance] DB caching for taxonomy_get_tree() » [performance] DB caching for \Drupal\taxonomy\TermStorageController::loadTree()
Issue summary: View changes
andypost’s picture

This is a tricky one.
Suppose we need to store only tree structure because whole entities are entity cache territory.
otoh any static cache affect "statability" of the controller/service...

So maybe better to abstract "tree-handling" into separate service?
We already have one after https://www.drupal.org/node/2226481
This should allow contib to implement a site-specific handling and caching?

PS: I know that @amateescu have a Tree module ported for d8 so glad to get his opinion on that

amateescu’s picture

Assigned: amateescu » Unassigned

My opinion is that I will just do it in contrib and we can see later about moving it to core :)

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.