-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
Compute can_holser once per save to speed up d:
filter from ~20s to ~5s
#78950
base: master
Are you sure you want to change the base?
Conversation
d:
filter from 20s to 5sd:
filter from ~20s to ~5s
@@ -285,6 +292,9 @@ class Item_factory | |||
std::unordered_map<itype_id, ammotype> migrated_ammo; | |||
std::unordered_map<itype_id, itype_id> migrated_magazines; | |||
|
|||
// cache for holsters | |||
std::unordered_map<itype_id, std::vector<const itype *>> type_contained_in_holsters; |
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.
std::vector<std::reference_wrapper<const itype>>
would probably be a better fit than a std::vector<const itype *>>
.
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.
Actually, Item_factory::find
returns std::vector<const itype *>
. So I would reinterpret it here as a vector of references. (No big deal)
It seems that whenever working with vector of itype, we use pointers. It might be that the code is old.
Do you still think I should change it to refs?
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.
It seems that whenever working with vector of itype, we use pointers. It might be that the code is old.
I think it is just that the code is old, and everyone who has used the code since then has just kept it as is. There isn't any performance cost to converting a pointer to a reference, so I think they should be stored as references.
src/item_factory.cpp
Outdated
const holster_actor *ptr = dynamic_cast<const holster_actor *> | ||
( e.get_use( "holster" )->get_actor_ptr() ); | ||
const item holster_item( &e ); | ||
return ptr->can_holster( holster_item, itm ) && !item_is_blacklisted( holster_item.typeId() ); |
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.
Is the cache updated on blacklist changes?
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.
It is not. I guess we don't need this at all. Thanks for bringing this up whether it concludes to be not needed or completely wrong.
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 removed the check.
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.
Given the check exists in the old code, I would be wary that removing it removes functionality. That said, I don't really use blacklisting when I play, so I don't know what it would cause.
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 think we could refresh the cache on blacklistings... If that is wanted.
If you think this can be confusing, consider rewording |
- Second search with `d:` in crafting menu takes ~5 seconds instead of ~20 seconds
Could be. I don't like the "Can be stored in", it is probably broken. It doesn't list enough things, it probably only lists clothing. Compare Can be stored in the description on a plank and then search crafting menu for L:122cm. Some of those containers should be shown in "can be stored in", in my opinion. I am writing that because I don't know what the original intent was so I don't want to change the sentence without investigating what the list actually represents. That said, this PR doesn't care what it lists, it just caches it. |
Oh, I know now. Let's use the cache as a first line of defence, giving candidates. Then check these candidates. It will still reduce the number of items to check from like 8000 to between 0 and 40. A bit slower. But there will be no change in functionality. Gonna sleep now. |
This isn't correct. Some items can change volume/weight/length so they won't fit in your precomputed holsters anymore. A quick example is a |
You are commenting the existing code, not the last idea, right? With the last idea #78950 (comment), we would get candidates that need checking. I asked on Discord and what breaks the last idea are items, that can get smaller, not bigger. They then could fit into more containers than precomputed. |
Or can't we just tell if item is modified? If it is, don't use this cache. |
Is this ready to be merged? |
I don't believe so, as it currently incorrectly handles items that can be modified to be smaller. The gun is a clear example, but the police baton or collapsing mop would also be a problem. |
I am converting this to a draft to clarify that it is not ready (in addition to the unresolved conversations). I updated the OP on what needs to be done. |
Summary
Performance "Compute can_holser once per save to speed up
d:
filter from ~20s to ~5s"Purpose of change
d:
filter from 20s to 5s (all searches after the first search)d:
to ~32% #78945 is included in the 20s.short string
info generates too long (725 ms) #78749It is not the purpose, but this PR changes the "Can be stored in" item info:
Before this PR, it checks volume etc. of this item and finds anything this can fit in.
Can be stored for half filled camera bag respects the contents of camera bag.
After this PR, only the type is checked, so it lists all items that this item would fit into, if this item was empty. Honestly, I think this is an improvement.
Can be stored for half-filled camera bag behaves as if camera bag was empty.
Honestly, I think this is an improvement. I expect this menu to be "What could this item fit into" rather than "What does this item fit into right now."
Also, I don't use it and it consumes so much resources for this and item_info. This is a way to keep it and have it fast.
Describe the solution
Make a new cache for can_contain for holsters in item_factory. The cache stores all items itype fits into. Since itypes are created on loading a save, we can start caching at that point. Since itypes are frozen, the cache is valid until the save is Quit. (See additional context for
m_runtimes
).To be done:
item::contained_in
(name pending) using this cache but making it work for the above two problems.Describe alternatives you've considered
To prevent the change described in purpose:
Testing
d:
filter - takes about 20 seconds.Profiling
First search
Second+ search
Additional context
I do not understand what
m_runtimes
insrc/item_factory.h
are, but I assume they are camp-related.We discussed it here https://discord.com/channels/598523535169945603/598529174302490644/1325252546281078814
As long as they are not actual items that can contain things, this PR doesn't care. If they are, this should invalidate the cache whenever
m_runtimes
changes.item_factory::add_item_type
is dead code, see remove dead code #79004.