-
Notifications
You must be signed in to change notification settings - Fork 395
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
Don't sort children on node addition to save on performance #68
Conversation
Everytime a child is added to the CommandNode, the children was sorted. This action is extremely heavy with large node trees such as Minecraft. From what I can see, sort order was not even needed by type since the dispatcher parse checks argument and literal nodes instead. Testing on /bossbar command seemed to have no impact to behavior. Credit to PaperMC/Paper@dda9680 Co-authored-by: virustotalop <virustotalop@gmail.com>
This issue causes significant CPU hits every time a player logs in or changes world, so it provided a substantial improvement. See numbers here: PaperMC/Paper#3154 (comment) |
Hmm, it is good to improve load-time performance, but by switching to a tree map, how is the lookup performance at runtime? Minecraft doesn't add to the map any more at runtime, so the actual impact isn't that big. Theoretically a tree map lookup shouldn't be slower than that of a linked hash map. Just need some profiling to show the actual performance at runtime (after all the command children are added). |
I don't believe that map is even queried at runtime, the other maps are used instead. But regardless, worrying about get performance is a premature optimization, as this is not hot code. Tree map will absolutely be fast enough for something that runs so infrequently even if it was queried. |
Conclusion of the debate above: The rest of replacing linked hash map with tree map is pointless. The new tree map does not preserve the iteration order that the linked hash map could guarantee as the tree map is comparing the string key instead of the command node value as done in linked hash map previously. |
The lines that are sorting the map was the original cause of the performance degradation. The idea was to use a TreeMap so that CommandNodes are sorted automatically. When I made the original patch it didn't seem like the behavior was changed due to LiteralCommandNode sorting by the name of the node anyways. I'm not super familiar with the structure of brigadier or how command nodes are resolved and how this section would effect behavior using a TreeMap instead of checking for a LiteralCommandNode first. I have ran this patch in production as well as using a TreeSet and a HashMap as discussed here and both seem to act the same at least to the client. This should probably be investigated further by someone who is more familiar with brigadier as I'm not sure how this would work for other servers, mods etc. |
Oh, that section would be prioritizing literal command nodes over other types of command nodes (presumably only argument command nodes), and then sort each type of node by their sorted key. brigadier/src/main/java/com/mojang/brigadier/tree/CommandNode.java Lines 173 to 180 in 9542f80
For instance, if we have subchildren apple <banana> cactus (<> denotes argument nodes), the original sort order would be apple cactus <banana> (literals first), while yours would be apple <banana> cactus (literal mixed with argument, sorted only by name)
|
since iteration order isn't important anyways.
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.
For those looking for priority of nodes, they should rather call getRelevantNodes and check than depending on the iteration order here.
Hmm, something actually happens here! Interesting 👀 |
Everytime a child is added to the CommandNode, the children was sorted.
This action is extremely heavy with large node trees such as Minecraft.
From what I can see, sort order was not even needed by type since
the dispatcher parse checks argument and literal nodes instead.
Testing on /bossbar command seemed to have no impact to behavior.
Credit to PaperMC/Paper#3172
Co-authored-by: virustotalop virustotalop@gmail.com