• Advertisement
Sign in to follow this  

Storing "additional versions" of objects in other objects?

This topic is 911 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Without being told that premature optimization should be avoided I would like to know what is happening when storing additional versions of objects in other objects for "reference". Yes, what we do every time when we create a object from a class. I specifically need to know this for Java. Are there just a pointers to it and doesn't this add all that much overheat? I have always wondered this and now I am creating something where I think this knowledge would come in handy.

 

Reason I want to know is that I have some "large" arrays of 50.000+ fairly small objects. I need access to these arrays in a Class where I will create "many" hundreds of objects from.

 

For each method where I need the arrays I could pass it along as a parameter but the way I am currently building things, I rather store it in each instance of the class when constructing the object. I could also make the Arrays public static if that would help. But my guess is there just will be many pointers to all these arrays the same way there would be a pointer to a int in any other object. Unless I would actually deep copy it of course.

Edited by menyo

Share this post


Link to post
Share on other sites
Advertisement


Are there just a pointers to it and doesn't this add all that much overheat?

 

That's correct. Although your terminology "additional versions" is confusing.

 

The only real impact it could have is to slow down garbage collections. The more objects hold references to things, the slower it will be for the garbage collector to traverse all objects to see if they can be collected. However, by storing a reference to the array in an object, you're only creating 1 extra reference to be traversed per instance of that object. So the effect in your case would be negligible unless you're creating thousands of these objects. 

Share this post


Link to post
Share on other sites
The design pattern is called "Flyweight", which does exactly what you suggest.

Your solution does cause a new problem you may not be aware of.
If you create an object to share, you put it in a map or array, so you can find it again, and give a new reference out when needed.
This all works great.

The only issue is now, how do you decide when the object in your map or array can be removed? (nobody uses it anymore, so it can be removed).
However there is still a single reference to the object, namely from your map or array, for future finding the object again.
As a result, it won't get garbage collected ever, and your map or array keeps growing.

The solution to this problem is done by weak references. It's a normal reference, but it doesn't count in garbage collection. If an object is only referenced by weak references, it does get destroyed anyway.
As a result, an object accessed through a weak reference may disappear suddenly. You always have to check existence of the referenced object before accessing.
I don't know the details of how Java does this, but you may want to consider using this idea.

Share this post


Link to post
Share on other sites

Yeah my terminology isn't up to par. I'm trying to learn additional proven design patterns, I know quite a view like builder and factory patterns but I catch myself too often by using a language like Lego. I am aware that in order to improve significantly I need to learn when to implement different proven patterns.

 

Now for the problem with the garbage collector, I am curious if this does form a significant problem. The array is my actual tile map and the Abilities will be using the tilemap to calculate things. A ability can add a action component and for example a ProjectileAction calculates accuracy first then it will find the perfect direction to shoot at and alter it based on this accuracy value. Then it casts a ray and needs to check if it hits something on the map (the array) or a "active" creature.

 

A lot of abilities require the ProjectileAction component.

  • A basic arrow uses it and after that the Ability will follow up with a DamageAction to deal damage to the target if there is one supplied by the ProjectileAction (miss or hit).
  • A fireball uses it too, then follows up with a AreaOfEffectAction -> DamageAction -> StatusEffectAction (burn) for all the creatures in the list supplied by the AreaOfEffectAction.
  • I might have to change the name of ProjectileAction but a movement action could also use it. Let's say I have a rush ability that instantly put a player creature next to another. I would implement the ProjectileAction with perfect accuracy and if it does not supply the same as the original target the ability fails. I would just need to set a flag on creation and a if statement on execution.
  • Many more abilities can use this ProjectileAction, a spike trap, a ice blast that shatters on impact, a lightning spell that chains to another target on impact, etc.

Hundreds more can be created using either this ProjectileAction or other actions that might require other objects. I am currently all storing them in Ability and send the Ability object to each AbilityAction so it has access to whatever it wants like name, chosen target, list of effected targets, list of creatures, the map, the pathfinding graph, etc.

 

Anyway, since the tile map should never be disposed of unless the application exits I think there is no issue regarding the garbage collector. Yes, the player can back out of the game to the main menu. But unless the player is idling there he will soon need that tile map anyway.

 

But now I'm thinking of using a public static for the map. Since at all time there should be only one map. The map might change partially or switched out for a completely different map but at all times there will only be one. But then what about my list of creatures in my creature handler? It will not contain hundreds of creatures but currently I do need it in some AbilityActions. So would that justify to make it public static as well? Afaik It would just save memory at the cost of completely open readability.

Edited by menyo

Share this post


Link to post
Share on other sites

I am aware that in order to improve significantly I need to learn when to implement different proven patterns.

I treat patterns the other way around. I implement it myself first, and then compare my solution with the pattern to check if I missed something. Often the answer is that I skipped some parts because I don't need the generality that the pattern assumes.
 

Anyway, since the tile map should never be disposed of unless the application exits I think there is no issue regarding the garbage collector.

This sounds correct to me.
There is perhaps an issue if some tiles only occur at some levels, but it is probably too much work to make a special case for that.
 

But now I'm thinking of using a public static for the map. Since at all time there should be only one map. The map might change partially or switched out for a completely different map but at all times there will only be one. But then what about my list of creatures in my creature handler? It will not contain hundreds of creatures but currently I do need it in some AbilityActions. So would that justify to make it public static as well? Afaik It would just save memory at the cost of completely open readability.

You should aim for the conceptually correct solution first, and only deviate from that if forced by other constraints, imho.
A public static variable says to me it never changes, and it doesn't depend on level-specific things. You can make the monster list static, but then you sort of should make the entire game level static. Personally, I don't have major problems with that, but you might.

 

If you keep the monster list in the current level (assuming it is there), then the actions that depend on it also belong in the current level. This in turn implies that access to the tile map should be in the level.

If the majority of the actions is static information (independent of the actual level), you could make it a 2-stage thing. From the level, you access the tile map. The monster-dependent actions get resolved in the level, all other tiles get resolved in a private static part of the level, so you don't have to set it up every time a new level starts.

Share this post


Link to post
Share on other sites

There is perhaps an issue if some tiles only occur at some levels, but it is probably too much work to make a special case for that.

 

But if those tiles are not referenced in the Array they will get disposed of right?

 

 

 


You should aim for the conceptually correct solution first, and only deviate from that if forced by other constraints, imho.
A public static variable says to me it never changes, and it doesn't depend on level-specific things. You can make the monster list static, but then you sort of should make the entire game level static. Personally, I don't have major problems with that, but you might.

 

A public static final variable sound to me it never changes. A static variable just says there is only one of it no matter how many objects are created from the class where the static variable belongs to.

 

Yes essentially everything where there is only one from can be static. Like I said, making things public static may very well save memory and performance but it isn't "good" design which is essential for larger projects.

 

Anyway, since there should only be about (Active Creatures * 2 AbilityActions) active at any one moment I would not foresee any problems. Just had to make sure it would not be a problem if eventually hundreds of Abilities would cause problems with having all these large objects in them.

Edited by menyo

Share this post


Link to post
Share on other sites

But if those tiles are not referenced in the Array they will get disposed of right?
correct, assuming it is not used elsewhere either.

 

In that view, there is another option you can consider.

When you load a map, keep track of what you created for the level, and re-use anything you made, or create if you didn't create it before.

 

At the end of loading, let go of the tracking map. (clear it, set it to null). Now you have a level with shared objects but nothing else refers to them, so if the player leaves the level, the objects get deleted as well.

 

A public static final variable sound to me it never changes.
Good point.

Share this post


Link to post
Share on other sites

Yes essentially everything where there is only one from can be static. Like I said, making things public static may very well save memory and performance but it isn't "good" design which is essential for larger projects.

 
It sounds like you currently have a very large array and that many objects/classes have a reference to it. But you still only have *one* instance of that array and making a single public static reference to it isn't going to change that. The only memory you'll save is the memory used to store the references to the array, and those are pretty small. Unless you have thousands of such references then the difference is going to be negligible.

 

I would rethink the idea that the tile map should never be disposed until the application exits. If you have multiple levels then it makes sense to load each level into its own tile-map array. Then, when the user switches levels, you replace the current level's tile-map with the one for the new level. At that point the old tile-map will no longer be referenced and will be reclaimed by the garbage collector.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement