Remove unnecessary durability check in ItemStack#isSimilar #9979
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I know that this looks like a stupid optimization that doesn't do anything, but hear me out:
getDurability()
ain't free, when you callgetDurability()
, it callsgetItemMeta()
, which then allocates a newItemMeta
or clones the current item's item meta.However, this means that we are unnecessarily allocating useless
ItemMeta
objects if we are comparing one or more items that don't have any durability (if they had durability, they would have a non-null meta), and this impact can be noticed if one of your plugins has acanHoldItem
function that checks if a inventory can hold an item by looping thru the player's inventory, especially if the plugin is checking this multiple times in a tick.To avoid this, we can just... not check for the item's durability! Don't worry, the durability of the item is checked when it checks if both item metas are equal.
This is a leftover from when checking for the item's durability was "free" because the durability was stored in the
ItemStack
itself, this was changed in Minecraft 1.13, however theisSimilar(...)
method hasn't been changed since it was added in 2012.Of course, maybe this patch is a bit useless? There is a performance benefit if you remove that call since you avoid initializing/cloning a
ItemMeta
if one or both of the items have a nullItemMeta
+ removes a deprecated call + improves the code to match how items work in a post-1.13 world, but the benefit is so so so smol (really only helps plugins that are constantly checking if an item is similar to another, which is my case, where one of my plugins allows players to "quick harvest" their farms, and for each crop it needs to check if the drops fits on their inventory) that maybe it could just be ignored, after all, there's also the work of maintaining this diff to fix something that just boils down to "well now its correct and there is a super tiny perf improvement". (Maybe this should be upstreamed to Spigot since they are the ones who are maintaining Bukkit? but paper my beloved tho...)(The reason I found out that this had a performance impact was because the
getDurability()
was using 0.08ms each tick in one of my plugins according to spark... yeah, sadly it ain't a super big crazy optimization, the performance impact would be bigger if you have more plugins usingisSimilar(...)
tho, something something pick a function and make it fast or something like that)Keep in mind that
CraftItemStack
does overrideisSimilar()
, and the overriden method also checksgetDurability()
. However,CraftItemStack
getDurability()
actually gets the damage directly from the NBT tags. Maybe both checks should be removed? "oh but ifCraftItemStack
overrides this method then your patch is USELESS!!!" actually not because you initialize theItemStack
class directly, andCraftItemStack
delegates to ItemStack'sisSimilar()
if the stack being compared is not aCraftItemStack
, see this debug log:[org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack] CraftItemStack isSimilar comparing ItemStack{CRAFTING_TABLE x 1} (class org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack) to ItemStack{BEETROOT x 1} (class org.bukkit.inventory.ItemStack)
Example of a plugin code that uses
isSimilar(...)
: