-
Bug
-
Resolution: Fixed
-
1.19.4, 23w16a, 23w17a, 23w18a, 1.20 Pre-release 7, 1.20, 1.20.1, 23w31a, 23w32a, 1.20.2
-
None
-
Plausible
-
Commands, Performance
-
Normal
-
Platform
The bug
/execute store is a command that runs subsequent commands in a new command environment with a result consumer that consumes command results. This result consumer is carried over across /function, and is invoked every time a command within the function is executed. This behavior is natural when considering that other elements such as positions and entities are similarly carried over. However, this behavior introduces overhead when obtaining the result of /function with /execute store. In particular, when obtaining the result of a recursive function with /execute store, the cost per command is quadratic with respect to the recursion depth.
How to reproduce
Simple case
- Run
/function mc-262027:simple-a
data modify storage mc-262027: simple set value 0
execute store result storage mc-262027: simple int 1 run function mc-262027:simple-b
# This command prints 0. tellraw @a {"nbt": "simple", "storage": "mc-262027:"} say mc-262027: # This command prints 1 because the result consumer was applied to the result value of `/say <message>` (1). tellraw @a {"nbt": "simple", "storage": "mc-262027:"}
Recursive case
In the case of recursion, reproduction steps become a bit more complicated. This is because result consumers perform a set operation, making it difficult to observe whether they have been executed multiple times.
- Run
/gamerule maxCommandChainLength 12
- Run
/function mc-262027:recursive-a
- Run
/tellraw @a {"nbt": "recursive", "storage": "mc-262027:"}
→ formatted output:
[ {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, {_: 0}, ]
From the above output, we can see that the function mc-262027:recursive-b has recursed 5 times, and the result consumers have been invoked a total of 15 times (= (5 * (5 + 1)) / 2), which is quadratic.
data remove storage mc-262027: recursive function mc-262027:recursive-b
# The NBT path [{_: 1}] adds {_: 1} to the target list tag if it is not present. # Then, the NBT path _ sets 0 to the _ in all compound tags within that list tag. # As a result, the list tag loses {_: 1} once again. # By repeating this process, elements can be continuously added to the list tag. # Note that for this reproduction function, the cost is **quartic** due to searching within the list tag. execute store result storage mc-262027: recursive[{_: 1}]._ int 0 run function mc-262027:recursive-b
- is duplicated by
-
MC-125145 Cannot change scoreboard value within "execute store"
- Resolved