-
Notifications
You must be signed in to change notification settings - Fork 534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improves item comparison performance #3258
Improves item comparison performance #3258
Conversation
There are a lot of situations where SF items are CraftItemStacks not SlimefunItemStacks This is most obvious with cargo and has been a big bottleneck there (~60%). This PR addresses the cargo specific point but will probably carry over to other parts of the code here and in addons. In Cargo we wrap the items being used for comparison, these items can still be SF items just, they look like regular Bukkit items. So, the is item similar check should account for this. With this change it will check if it's wrapped and if it has item meta, if it does then it will try and get IDs to compare. Otherwise, fall back to usual item meta comparison. This improves cargo performance by about 60% when filtering SF items.
Your Pull Request was automatically labelled as: "💡 Performance Optimization" |
Kudos, SonarCloud Quality Gate passed! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The optimisation makes a lot of sense; LGTM.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me
With the help of @Sefiraat I have done some timings on a HUGE base, here are the results: Non optimized:
Optimized:
50% reduction!!! |
Not even crediting me for running these test bish |
Love it.... the owners of this server will, in advance, thank you greatly for this when it's all approved xD |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I will merge this on the weekend.
Also, we really should focus on writing very extensive unit tests for this method soon.
It is so widely used, yet not even remotely covered by tests.
src/main/java/io/github/thebusybiscuit/slimefun4/utils/SlimefunUtils.java
Show resolved
Hide resolved
// Slimefun items may be ItemStackWrapper's in the context of cargo so let's try to do | ||
// an ID comparison before meta comparison |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
multiline comment 👀
// Slimefun items may be ItemStackWrapper's in the context of cargo so let's try to do | |
// an ID comparison before meta comparison | |
/* | |
* Slimefun items may be ItemStackWrapper's in the context of cargo so let's try to do | |
* an ID comparison before meta comparison | |
*/ |
Optional<String> possibleSfItemId = Slimefun.getItemDataService().getItemData(possibleSfItemMeta); | ||
Optional<String> itemId = Slimefun.getItemDataService().getItemData(itemMeta); | ||
|
||
if (possibleSfItemId.isPresent() && itemId.isPresent()) { | ||
return possibleSfItemId.get().equals(itemId.get()); | ||
} else { | ||
return equalsItemMeta(itemMeta, possibleSfItemMeta, checkLore); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I have time to look at this a little closer, I spot a way we can optimize this further.
If possibleSfItemMeta
has no id, we don't need to extract the id from itemMeta
, reducing it by one avoidable call.
Not the prettiest but you get the idea
Optional<String> possibleSfItemId = Slimefun.getItemDataService().getItemData(possibleSfItemMeta); | |
Optional<String> itemId = Slimefun.getItemDataService().getItemData(itemMeta); | |
if (possibleSfItemId.isPresent() && itemId.isPresent()) { | |
return possibleSfItemId.get().equals(itemId.get()); | |
} else { | |
return equalsItemMeta(itemMeta, possibleSfItemMeta, checkLore); | |
} | |
Optional<String> possibleSfItemId = Slimefun.getItemDataService().getItemData(possibleSfItemMeta); | |
if (possibleSfItemId.isPresent()) { | |
Optional<String> itemId = Slimefun.getItemDataService().getItemData(itemMeta); | |
if (itemId.isPresent()) { | |
return possibleSfItemId.get().equals(itemId.get()); | |
} | |
} | |
return equalsItemMeta(itemMeta, possibleSfItemMeta, checkLore); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scratch the above.
To declutter this:
We should implement a CustomItemDataService#compare(...)
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll make a follow-up commit.
Description
There are a lot of situations where SF items are CraftItemStacks not SlimefunItemStacks
This is most obvious with cargo and has been a big bottleneck there (~60%).
This PR addresses the cargo-specific point but will probably carry over to other parts of the code here and in addons.
In Cargo we wrap the items being used for comparison, these items can still be SF items just, they look like regular Bukkit items. So, the is item similar check should account for this.
With this change, it will check if it's wrapped and if it has item meta, if it does then it will try and get IDs to compare. Otherwise, fall back to the usual item meta comparison. This improves cargo performance by about 60% when filtering SF items.
The reason this change has such a big impact is simple, the display name code is terrible. It will decode JSON and create message components just for getting the name. It's very awkward and not nice to use. The
ItemMeta#getDisplayName
alone accounts for 60% of cargos #insert processing time in the numerous Spark reports we have received.Call stack for this:
CargoUtils#insert
CargoUtils#matchesFilter
ItemFilter#test
SlimefunUtils#isItemSimilar
Proposed changes
Check if an item is an
ItemStackWrapper
and try to compare IDs there too. It will only do it currently if both items are SlimefunItemStacks but that isn't the case a lot of the time.Related Issues (if applicable)
N/A
Checklist
Nonnull
andNullable
annotations to my methods to indicate their behaviour for null valuesRequesting a review from @md5sha256 who initially introduced this wrapper code