Skip to content

Conversation

@Ivorforce
Copy link

@Ivorforce Ivorforce commented Jan 24, 2026

This accelerates _resolve_toctree. In Godot's documentation, this saves ~15m of ~60m (25%).

New profile results after optimizing:

results.prof.zip

Explanation

As found in #14277, the function _resolve_toctree appears to use _toctree_copy to prune it. The original is discarded, wasting CPU time.
This PR changes the operation to prune in-place.

I've tested this with https://github.com/godotengine/godot-docs, and at a glance can find no regressions. However, since I'm not at all familiar with the codebase, this definitely needs an expert review :)

)
return

if isinstance(node, (nodes.reference, nodes.title)):
Copy link
Member

Choose a reason for hiding this comment

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

nodes.reference may be quite common so let us have the check early.

):
node: Element

if isinstance(node, (addnodes.compact_paragraph, nodes.list_item)):
Copy link
Member

Choose a reason for hiding this comment

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

Can you reorder all isintance checks from the more likely to the less likely chrck and prioritize early exits?

return

msg = f'Unexpected node type {node.__class__.__name__!r}!'
raise ValueError(msg)
Copy link
Member

Choose a reason for hiding this comment

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

Let us raise a TypeError instead.

_toctree_prune_seq(node, depth, maxdepth, collapse, tags, initial_call=True)


def _toctree_prune_seq(
Copy link
Member

Choose a reason for hiding this comment

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

Why not using a node transformer with a visitor pattern? (though... it could have surprising effects for subclasses as I am not sure the visitor is polymorphic)

@picnixz
Copy link
Member

picnixz commented Jan 24, 2026

Cutting of children may result in a bad tree at the end with some information possibly lost (e.g. the event handlers may have surprises)

@Ivorforce
Copy link
Author

Ivorforce commented Jan 24, 2026

@picnixz Thank you for the review!
Note that the function is virtually identical to _toctree_copy. All your comments appear to apply to that function as well as _toctree_prune. I think it's out of scope to change those in the same PR.

Cutting of children may result in a bad tree at the end with some information possibly lost (e.g. the event handlers may have surprises)

Do you think there's a way to address this without making a copy of the entire tree?

@picnixz
Copy link
Member

picnixz commented Jan 24, 2026

Unfortunately no. The simple fact that the current tests fail is also an indication that this changed the behavior :/

@Ivorforce
Copy link
Author

Ivorforce commented Jan 24, 2026

Am i understanding this right — there's no way to remove children from Node without breaking the tree entirely?
Edit: docutils' Node appears to have various element removal functions, so it at least thinks it's supported.

@picnixz
Copy link
Member

picnixz commented Jan 24, 2026

I need to check this again as I do not remember exactly what state is assumed here. However, any tree modifications that drop children may not necessarily be possible.

It is fine to make a copy as this becomes a transformed tree but an in-place transformation may not be preferrable (maybe changing the tests is also correct but we need to be careful of whether the tree is getting passed to event handlers at some point of the resolution)

@Ivorforce
Copy link
Author

Ivorforce commented Jan 24, 2026

Looking at the code again, I think I may just have mistransformed the return values for the in-place pruning. I'll try again.
Edit: Looks like that worked! Unit tests are passing.

@Ivorforce
Copy link
Author

Ivorforce commented Jan 24, 2026

Looks like the _toctree_prune is not pruning quite as harshly as _toctree_copy. I'm seeing some additional empty lists generated, like:

<ul class="simple">
</ul>

These aren't rendered in the browser, so this has no visual effect.

I'm not sure where that's coming from, as the nodes.bullet_list looks the same to me in both versions.

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