Hi everyone,
currently, in the macro transformation that executes all macros in the page, we search the whole XDOM for the macro block with the highest priority - and we do this again after executing a macro. The reason for this is that in theory macros have access to the whole XDOM, and thus they can add or remove macro blocks wherever they want. In practice, this rarely happens. In fact, most macros don’t even care about the order in which they’re executed.
If we knew more about the macros, there are two possible optimizations:
- Macros that guarantee that they’re fully isolated in the sense that their output only depends on the macro parameters and content (but not other elements present in the XDOM) and that don’t execute/transform their content could be executed in any order and as soon as we find them. This would apply to macros like
id
orcode
. - We could keep a priority queue of all remaining macro blocks and only re-build the queue after executing a macro that doesn’t guarantee that it won’t modify the XDOM.
The problem of optimization 2 is that it’s only beneficial once most macros indicate that they’re safe and until then it could actually make the performance worse. While building a priority queue is cheap, it’s still more expensive than just iterating over the macros. There is in theory the possibility to automatically detect if the XDOM is modified, but this seems hard, too. As many macros should fall into category 1, I think this should bring us most benefits.
Therefore, I propose the following changes:
- Introduce a method
boolean isExecutionIsolated(P parameters, String content)
inorg.xwiki.rendering.macro.Macro
that returnsfalse
by default. It should returntrue
if the execution is independent of the XDOM and doesn’t execute other macros. - When iterating over the XDOM to find the next macro to execute, we ask every macro if the execution is isolated, and if yes, we immediately execute it, and then continue the iteration.
The rationale to pass the parameters is to allow, e.g., the HTML macro to return true
if the wiki
parameter is false
. The macro transformation would cache the set of macros for whom isExecutionIsolated
returned false
in an IdentityHashMap
to avoid calling the method again and again.
What I’m wondering about is if the HTML macro is really isolated, though, as its results depends on whether the context is restricted and if the context author has script right. And in theory, there could be a higher-priority macro that is executed before the isolated macro that changes this. I’m not sure whether this is really something we should consider, it’s just a thought.
Wiki macros seem to use their position in the XDOM to compute an ID and thus they’re not truly isolated: xwiki-platform/xwiki-platform-core/xwiki-platform-rendering/xwiki-platform-rendering-wikimacro/xwiki-platform-rendering-wikimacro-store/src/main/java/org/xwiki/rendering/wikimacro/internal/DefaultWikiMacroRenderer.java at c99d501ed41cbee6a3c02ff927714531570789de · xwiki/xwiki-platform · GitHub - we could ignore this and allow wiki macros do declare themselves as isolated with a new property in the wiki macro descriptor. In general, we would still execute isolated macros in-order, so I think the IDs should still be stable. However, even with the current code, I doubt these IDs are unique (a macro that is executed after the current macro could insert content in the XDOM before the current macro that has the same ID as the current macro), so I’m not really sure what the idea of using the index is.
Do you have any opinions on this?