Tutorial:Optimizing a data pack
This tutorial shows how to make commands or a data pack performant, including best practices and methods to profile a data pack.
Best practices
When in doubt, always profile
Minecraft is a complex game. There are no rules that always apply and running commands can behave unexpectedly. When you are not sure which optimization to make, try both implementations and profile (see below).
Minimize commands running
This seems like an obvious rule, but it is one of the most effective ways to optimize commands.
One way of achieving this is by not running all commands every tick. Sometimes you can get away with running non-critical commands every N ticks.
Minimize NBT operations
Accessing or modifying NBT, especially on players is really expensive. This is because the game is essentially saving the entity to the format on disk, doing operations on that data structure, and then (in the case of modifying NBT) reading it back in to create an entirely new entity.
- execute as @a[nbt={SelectedItem:{id:"minecraft:apple"}}] run ...
+ execute if items entity @s weapon.mainhand apple run ...
When modifying items, use item modifiers instead of editing the NBT.
- data modify entity @s Item.count set value 10
+ item modify entity @s contents {function:"set_count",count:10}
Use predicates when you can.
- execute as @a[nbt={RootVehicle:{id:"minecraft:pig"}}] run ...
+ execute as @a[predicate=example:riding_pig] run ...
+
+ # the riding_pig predicate file:
+ {
+ "condition": "minecraft:entity_properties",
+ "entity": "this",
+ "predicate": {
+ "vehicle": {
+ "type": "minecraft:pig"
+ }
+ }
+ }
Minimize execute subcommands
- execute as @a[tag=hider] run effect give @s glowing
+ effect give @a[tag=hider] glowing
- execute as @a[tag=hider] if score @s timer matches 0.. run ...
+ execute as @a[tag=hider,scores={timer=0..}] run ...
- execute run say hi
+ say hi
Minimize @e selectors
Finding all matching entities in the world is expensive. If you have many repeated or similar selectors, consider combining them into a one and branching to a separate function where you will be able to use @s to target the entity cheaply.
- execute as @e[type=item] if items entity @s contents apple run ...
- execute as @e[type=item] if items entity @s contents cobblestone run ...
+ execute as @e[type=item] run function example:process_item
+
+ # in the process_item function:
+ execute if items entity @s contents apple run ...
+ execute if items entity @s contents cobblestone run ...
Include type checks in selectors
Always include a type= argument in selectors unless you intend to select all entity types. This allows the game to very cheaply filter out the entities that you don't want.
- execute as @e[tag=special_altar] run ...
+ execute as @e[type=marker,tag=special_altar] run ...
Minimize unnecessary macros
Calling a macro function has an overhead. Consider using them only when strictly necessary.
- $scoreboard players set @s example $(Age)
+ execute store result score @s example run data get entity @s Age
Used the cache for macros
Minecraft stores the last 8 parsed functions containing macro function.
So, if your macros have only 16 possible inputs, consider creating 2 functions with 8 possible inputs each to significantly improve performance.
Profiling
External links
| |||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||