-
Notifications
You must be signed in to change notification settings - Fork 32
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
Gloot 3.0: Poor performance when serializing #276
Comments
Hi! func serialize() -> Dictionary:
var result: Dictionary = {}
if protoset == null || _constraint_manager == null:
return result
result[_KEY_NODE_NAME] = name as String
result[_KEY_PROTOSET] = _serialize_protoset(protoset)
if !_constraint_manager.is_empty():
result[_KEY_CONSTRAINTS] = _constraint_manager.serialize()
if !get_items().is_empty():
result[_KEY_ITEMS] = []
for item in get_items():
result[_KEY_ITEMS].append(item.serialize())
return result
static func _serialize_protoset(protoset: JSON) -> String:
if !is_instance_valid(protoset):
return ""
elif protoset.resource_path.is_empty():
return protoset.stringify(protoset.data)
else:
return protoset.resource_path
func serialize() -> Dictionary:
var result: Dictionary = {}
result[_KEY_PROTOSET] = Inventory._serialize_protoset(protoset)
if _prototype != null:
result[_KEY_PROTOTYPE_ID] = str(_prototype.get_prototype_id())
else:
result[_KEY_PROTOTYPE_ID] = ""
if !_properties.is_empty():
result[_KEY_PROPERTIES] = {}
for property_name in _properties.keys():
result[_KEY_PROPERTIES][property_name] = _serialize_property(property_name)
return result As you can see, the number of times This is also backed by your first screenshot: You have 266 calls to The real question here is why is By looking at your stack trace I can see that it is called by func get_furniture_data() -> Array:
var furniture_data: Array = []
for furniture in collider_to_furniture.values():
if is_instance_valid(furniture):
furniture_data.append(furniture.get_data())
return furniture_data I didn't analyze the code any further, but I think it would be worth checking how many values |
That explains the 995 calls. Thank you for looking into it. I did some more testing, and the 995 calls are probably from a forest. Each tree has an inventory and each inventory has about 3 items. If there are 225 trees in one chunk, then unloading that chunk will cause about 1000 items to be serialized. Serializing 1000 inventory items should be easy, right? It works perfectly in Gloot 2: The issue concerning |
What exactly do you mean by "the protoset is build when the game starts"? Is it not stored in a JSON resource file? I suspect this might be the key detail here. In the general case static func _serialize_protoset(protoset: JSON) -> String:
if !is_instance_valid(protoset):
return ""
elif protoset.resource_path.is_empty():
return protoset.stringify(protoset.data) # Could be slooow
else:
return protoset.resource_path In that case If you are doing some kind of runtime protoset generation then you could consider saving it as a resource, so that it won't get converted into string every time an inventory or an item gets serialized (not 100% sure how exactly that would work, but I suppose ResourceSaver could be used for that). |
You're right. the generation and use of the protoset will be the key point here. The protoset is constructed here: The resulting So you're saying that it needs to be saved to a file and then loaded so it has a resource path. This is similar to what I did with item_protoset.tres in Gloot 2 so that should work for me. I will try that. |
I'm now loading an itemprotosets.json file:
I updated my save_protorype function to this:
You can see the file here: https://github.com/snipercup/CataX/blob/gloot-upgrade/ItemProtosets.JSON The issue I had is no longer there. The Inventory._serialize_protoset isn't taking up a lot of time. However, now I'm having an even bigger problem when de-serializing: Here, you can see that 6 Did I make a mistake in my itemprotosets.json file? Are there too many custom properties? |
I think your protoset file is fine. This time it seems like the problem is in I'll try to come up with a fix asap. |
A small update on this: After doing some more analysis, it turned out that most of the calls to the Prototype functions is justified, since the protoset you provided contains 286 prototypes and >2000 different properties in total. That said, I managed to optimize away some of the calls (e.g. I'll keep looking into this to see if I can come up with some additional optimizations. |
Thanks for your efforts. I'll keep an eye on your progress. If there's a new version to try then I'll see what the performance is at that time. My game runs fine on Gloot 2.x for now. |
I am upgrading from Gloot 2 to Gloot 3. I could do most of the work in one day. I'm excited to get Gloot 3 running because it has many benefits compared to 2.0.
The problem I'm running into is the performance when serializing. This is when my serialization happens:
This is what the performance monitor is telling me:
A chunk is about twice the size of what is visible here. You can see a row of furniture that needs to be serialized, and at the top is the kitchen_cupboard.
I don't know why it would call the serialize function 995 times. I don't think I have that many items in a chunk and it will unload at most 3 chunks at a time. This performance issue is not present in Gloot 2.0. If possible, I don't want to serialize the protoset at all since there is only one used in the entire game and I can save it elsewhere if needed.
I am building the protoset here:
https://github.com/snipercup/CataX/blob/96caee3f39b58d7135ceeaacf85dc9f3d7578cdd/Scripts/Runtimedata/RItems.gd#L124-L131
And then I'm calling:
https://github.com/snipercup/CataX/blob/96caee3f39b58d7135ceeaacf85dc9f3d7578cdd/Scripts/item_manager.gd#L691-L692
What can I do to mitigate the performance hit?
The text was updated successfully, but these errors were encountered: