Optimization

How can I optimize my functions?

Always remember the number one rule of optimization, and that is:

don’t.

This faq will cover how to optimize your functions, but be warned: if you don’t fully understand what you’re doing, don’t do it. You’re likely to hurt your program. Here’s an example. Someone wants to optimize this command:

execute as @e[tag=foo] run data modify entity @s NoGravity set value 1b

and they think “What if we limited it to only select things with no gravity already?”

execute as @e[tag=foo,nbt={NoGravity:0b}] run data modify entity @s NoGravity set value 1b

The problem is, the second one deserializes too. It’s far less efficient. As explained here, an entity doesn’t store its nbt; it’s dynamically created on the fly. Thus, selecting with the nbt predicate means the entity has to fully deserialize themselves, like saving a world.

The second version only requires the entity serialize themselves, like loading in a world (the first still requires this).

That aside, here are some optimization tips

NBT

Avoid NBT as much as possible. You can often replace nbt selectors with predicates, which don’t operate on nbt. This avoids entity serialization. NBT modifications are a bit less avoidable, but try to limit them to one command only.

Storage NBT is not inefficient like normal nbt, so use it to help reduce operations. For example, you could turn

data modify entity @s Foo set from entity @p Foo
data modify entity @s Bar set from entity @p Bar
data modify entity @s Quux set from entity @p Quux

into

data modify storage foo Player set from entity @p {}
data modify storage foo Target set value {}
data modify storage foo Target.Foo set from storage Player.Foo
data modify storage foo Target.Bar set from storage Player.Bar
data modify storage foo Target.Quux set from storage Player.Quux
data modify entity @s {} merge from storage foo Target

It’s more verbose, but only has one serializing and deserializing operation. Remember, NBT isn’t cached at all.

As a note, multiple operations in a copy_nbt item modifier are fine, since they all act on the same NBT.

There are a few more things you can do, like replacing an item id check every tick with a tagged system (ask me about that, since that wasn’t clear at all).

Ticking functions

Minimize commands in a ticking function. It’s a simple as using advancement triggers instead.

Selectors

Every time you use a selector, it has to filter through the whole list of entities in the world. Here are some guidelines:

Also think about whether you need something extra on a selector! A common “optimization” I see is:

execute if entity @e[type=item,limit=1] run ...

Note the limit=1. Let’s see how the game processes it without it:

Now with it:

limit=1 still is another filter step; passing items are transferred to a new list. As you can see, it’s clearly less efficient; in fact, it requires an allocation, which is definitely inefficient.