Java-Gaming.org Hi !
Featured games (81)
games approved by the League of Dukes
Games in Showcase (513)
Games in Android Showcase (119)
games submitted by our members
Games in WIP (575)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  BIC BOI memory leak issue. Known cause. need fix  (Read 907 times)
0 Members and 1 Guest are viewing this topic.
Offline Kyperbelt

Junior Duke


Medals: 1



« Posted 2013-11-07 04:40:44 »

Ok so for the past 2 days i have been working on a map editor for a game im making and i noticed that the memory usage was getting out of control.
The most it has gone up to is 1,200,000K+ and once i saw that i knew something was wrong since not even Wow takes that much.

so i did some digging around and i noticed i had like 50,000 instances of an int[][] array. Now i dont know if its something wrong with my code or just gc is too slow but i need to fix it now before i continue.

This next bit of code is where the new arrays are being made.
now notice there is a piece of code that removes the item World which contains the array
from the linkedlist. now i was under the impression that once an object is no longer referred to
it will be collected and the memory freed up.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
package dragonhawk.monsters.mapeditor.editor;

import java.util.LinkedList;

import dragonhawk.monsters.mapeditor.Log;
import dragonhawk.monsters.mapeditor.world.World;

public class UndoManager {
   
   public static final int MAX_UNDO = 6;
   
   private static UndoManager UM = new UndoManager();
   
   public static UndoManager getUndoManager(){
      return UM;
   }
   
   private Editor ed;
   
   private LinkedList<World> undos;
   private int current_spot = 0;
   
   
   private UndoManager(){
      undos = new LinkedList<World>();
   }
   
   public void addWorldToCurrent(World world){
      ed=Editor.getEditor();
      undos.add(world);
   }
   
   public void undo(){
      if(hasUndo()){
         current_spot--;
         ed.WM.setCurrentWorld(undos.get(current_spot));
         Log.sLog("undid ");
      }
         
   }
   
   public void redo(){
      if(hasRedo()){
         current_spot++;
         ed.WM.setCurrentWorld(undos.get(current_spot));
      }
   }
   
   
   /**
    * before editing add an edit point to the undo list
    * @param world
    */

   public void addEditPoint(World world){
      Log.sLog("current array size:"+undos.size());
      current_spot++;
      Log.sLog("current spot in array:"+current_spot);
     
      Log.sLog("edit point added");
      //if an edit was made while there was edit points past the current spot
      //crop linkedlist
      if(current_spot<undos.size()){
         while(current_spot<undos.size()){
            undos.removeLast();
         }
         System.gc();
         undos.add(world.copy());
      }else{
         undos.add(world.copy());
      }
     
      //set the current workspace world to the current editpoint spot
      ed.WM.setCurrentWorld(undos.get(current_spot));  
      Log.sLog("current edit point"+current_spot);
   }
   
   public boolean hasRedo(){
      if(current_spot<undos.size()-1)
         return true;
      return false;
   }
   
   public boolean hasUndo(){
      if(current_spot>0)
         return true;
      return false;
   }
}


and the other culprit under suspicion is the way i copy my World object but im still somehow stumped

World.java
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
package dragonhawk.monsters.mapeditor.world;

import java.util.HashMap;
import java.util.Random;

import dragonhawk.monsters.mapeditor.editor.Xerox;


/**
 * **********************************
 * >>WORLD<<REGION<<CHUNK<<TILE>>INSTANCE>>WORLD>>
 *
 * @author Jonathan Camarena
 * **********************************
 */

public class World implements Xerox{
   
   public static final int MIN_WORLD_WIDTH = 2; //width in regions
   public static final int MIN_WORLD_HEIGHT = 1;//height in regions
   
   private Region[][] regions ;
   private int width;
   private int height;
   
   private int unique_id;
   
   public String ref;
   
   private HashMap<String,Instance> instances;
   
   public World(){
      unique_id = new Random().nextInt(3000);
      createEmtpyRegions();
   }
   
   public World(Region[][] regions){
      this.regions = regions;
      width = regions.length;
      height = regions[0].length;
      unique_id = new Random().nextInt(3000);
   }
   
   public void createEmtpyRegions(){
      width = MIN_WORLD_WIDTH;
      height = MIN_WORLD_HEIGHT;
      regions = new Region[width][height];
      for (int y = 0; y < height; y++) {
         for (int x = 0; x < width; x++) {
            regions[x][y] = new Region(x,y);
         }
         
      }
   }
   
   public int getUniqueID(){
      return unique_id;
   }
   
   public boolean setRef(String ref){
      if(ref == null || ref.isEmpty() || ref.equals("")){
         this.ref = ref;
         return true;
      }
      return false;
   }
   
   public Region getRegionAtLocation(int x, int y){
      return regions[x][y];
   }
   
   public World copy(){
     
      Region[][] copy = new Region[width][height];
     
      for (int y = 0; y < height; y++) {
         for (int x = 0; x < width; x++) {
            copy[x][y] = regions[x][y].copy();
         }
      }
      return new World(copy);
   }
   

}


World has regions, regions have chunks, chunks have tiles.
Now every other object down to the base is copied in this way. that way nothing is referencing the last.a (Deep copy if you will)
The next class is the Tile class which is the only real class that is making these int arrays
Tile.java
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
package dragonhawk.monsters.mapeditor.world;

import java.util.Arrays;

import dragonhawk.monsters.mapeditor.editor.Xerox;

public class Tile implements Xerox {
   public static final int TILESIZE = 16;
   
   private TileProperties properties;
   
   public Tile(int x, int y){  
      properties = new TileProperties(x,y,false,false);
   }
   
   public Tile(TileProperties properties){
      this.properties = properties;
   }
   
   public void setTileProperties(TileProperties properties){
      this.properties = properties;
   }
   
   public TileProperties getTileProperties(){
      return properties;
   }
   
   public Tile copy(){
      return new Tile(properties.copy());
   }

   
   public class TileProperties implements Xerox{
      public static final int NUM_OF_LAYERS = 3;
      public static final int NUM_OF_SHEET_REF_COORDINATES = 2;
     
      private int x;
      private int y;
      private Layer[] layers;
      private boolean isBlocked;
      private boolean animated;
     
      public TileProperties(int x, int y,boolean isBlocked, boolean isAnimated){
         setUpEmptyLayers();
         this.x = x;
         this.y = y;
         this.isBlocked = isBlocked;
         this.animated = isAnimated;
      }
     
      public void setUpEmptyLayers(){
         layers = new Layer[NUM_OF_LAYERS];
         for (int i = 0; i < layers.length; i++) {
               layers[i] = new Layer(new int[]{-1,-1});
           
         }
      }
     
      public int getX(){
         return x;
      }
     
      public int getY(){
         return y;
      }
     
      public void block(boolean blocked){
         isBlocked = blocked;
      }
     
      public void block(int layer, boolean blocked){
         isBlocked = blocked;
      }
     
      public boolean isBlocked(){
         return isBlocked;
      }
     
      public boolean isAnimated(){
         return animated;
      }
     
      public Layer[] getLayers(){
         return layers;
      }
     
      public void setLayers(Layer[] layers){
         this.layers = layers;
      }
     
      public boolean isLayerEmpty(int layer){
         if(layers[layer].layerdata[0] == -1)
            return true;
         else return false;
      }
     
      public int[] getLayerData(int layer){
         return layers[layer].getData();
      }
     
      public void setLayerRef(int layer, int[] ref){
         setLayerRef(layer, ref[0], ref[1]);
      }
     
      public void setLayerRef(int layer, int x, int y){
         int ref[] = {x,y};
         layers[layer].setData(ref);
      }
     
      public TileProperties copy(){
         TileProperties cprop = new TileProperties(x,y,isBlocked, animated);
         Layer[] copy = new Layer[layers.length];
         for (int i = 0; i < copy.length; i++) {
            copy[i] = layers[i].copy();
         }
         cprop.setLayers(copy);
         return cprop;
      }
     
     
   }
   
   public class Layer implements Xerox{
     
      private int layerdata[];
     
      public Layer(int[] layerdata){
         this.layerdata = layerdata;
      }
     
      public int[] getData(){
         return layerdata;
      }
     
      public void setData(int[] data){
         layerdata = data;
      }

      public Layer copy() {
         int[] copydata;
         copydata = Arrays.copyOf(layerdata, layerdata.length);
         Layer copy = new Layer(copydata);
         return copy;
      }
   }
   
   public static int[][] copyOf(int[][] original) {
          int[][] copy = new int[original.length][];
          for (int i = 0; i < original.length; i++) {
              copy[i] = Arrays.copyOf(original[i], original[i].length);
          }
          return copy;
   }
}


Now i will continue to google this further on my own but if anyone is able to help me that would be much appreciated. i will be happy to provide more additional information if needed.
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #1 - Posted 2013-11-07 07:26:25 »

1  
2  
3  
4  
5  
6  
7  
   public static int[][] copyOf(int[][] original) {
          int[][] copy = new int[original.length][];
          for (int i = 0; i < original.length; i++) {
              copy[i] = Arrays.copyOf(original[i], original[i].length);
          }
          return copy;
   }


What?  Huh You can do that?
Have various length second dimension like that?
copy is a 2d array, and yet you are accessing it in a single dimension? and also calling new on undefined size?
I thought it had to be a 'rectangle' and not have various length columns per each row(or vice versa)



Also does your program grow in size, if you just let it idle and not do anything?  or only when you keep using it? (making edits/modifications/etc..)


Lastly, even though that's where it may appear to have the duplicates existing, it doesn't mean this is where the root of the cause is. 


"Experience is what you get when you did not get what you wanted"
Offline lcass
« Reply #2 - Posted 2013-11-07 07:43:07 »

I would say make a clearup method that runs through all your code removing dead arrays. What it sounds like is when you call undo you are not clearing up the arrays you have created which just clogs up your memory
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Kyperbelt

Junior Duke


Medals: 1



« Reply #3 - Posted 2013-11-07 07:47:06 »

1  
2  
3  
4  
5  
6  
7  
   public static int[][] copyOf(int[][] original) {
          int[][] copy = new int[original.length][];
          for (int i = 0; i < original.length; i++) {
              copy[i] = Arrays.copyOf(original[i], original[i].length);
          }
          return copy;
   }


What?  Huh You can do that?
Have various length second dimension like that?
copy is a 2d array, and yet you are accessing it in a single dimension? and also calling new on undefined size?
I thought it had to be a 'rectangle' and not have various length columns per each row(or vice versa)

unfortunately copyof from arrays does not copy second dimension values :/ so i had to look around for a hack. but for the most part i thought this was my problem so i removed it from my logic in favor of a more controllable method


Quote
Also does your program grow in size, if you just let it idle and not do anything?  or only when you keep using it? (making edits/modifications/etc..)


Lastly, even though that's where it may appear to have the duplicates existing, it doesn't mean this is where the root of the cause is.  

idle growth is not substantial but when i do make edits it grew much larger than needed. i was making a lot of copies so that is understandable, but then when i would delete all the copies(clear the list of unwanted copies) it seems the GC would not collect and free up the memory and instead continue to grow.

I have just about given up and decided to hack my way around it. its not fixed but it is far more manageable.


new UndoManager.java
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
package dragonhawk.monsters.mapeditor.editor;

import java.util.ArrayList;
import java.util.List;

import dragonhawk.monsters.mapeditor.Log;
import dragonhawk.monsters.mapeditor.world.Chunk;
import dragonhawk.monsters.mapeditor.world.World;

public class UndoManager {
   
   public static final int MAX_UNDO = 20;
   
   private static UndoManager UM = new UndoManager();
   
   public static UndoManager getUndoManager(){
      return UM;
   }
   
   private Editor ed;
   
   private List<Chunk> undos;
   private int current_spot = 0;
   
   
   private UndoManager(){
      undos = new ArrayList<Chunk>();
   }
   
   public void addWorldToCurrent(){
      ed=Editor.getEditor();
      undos.add(ed.WM.getCurrentChunk());
   }
   
   public void undo(){
      if(hasUndo()){
         current_spot--;
         ed.WM.getCurrentRegion().switchChunkAt(ed.WM.getCurrentChunk().getX(),
               ed.WM.getCurrentChunk().getY(), undos.get(current_spot));
         Log.sLog("undid ");
      }
         
   }
   
   public void redo(){
      if(hasRedo()){
         current_spot++;
         ed.WM.getCurrentRegion().switchChunkAt(ed.WM.getCurrentChunk().getX(),
               ed.WM.getCurrentChunk().getY(), undos.get(current_spot));
      }
   }
   
   
   /**
    * before editing add an edit point to the undo list
    * @param world
    */

   public void addEditPoint(World world){
      Log.sLog("current array size:"+undos.size());
      current_spot++;
      Log.sLog("current spot in array:"+current_spot);
     
      Log.sLog("edit point added");
      //if an edit was made while there was edit points past the current spot
      if(current_spot<undos.size()){
         ArrayList<Chunk> newundos = new ArrayList<Chunk>();
         for (int i = 0; i < current_spot; i++) {
            newundos.add(undos.get(i));
         }
         undos = newundos;
         System.gc();
         undos.add(ed.WM.getCurrentChunk().copy());
      }else{
         undos.add(ed.WM.getCurrentChunk().copy());
      }
     
      //set the current workspace world to the current editpoint spot
      ed.WM.getCurrentRegion().switchChunkAt(ed.WM.getCurrentChunk().getX(),
            ed.WM.getCurrentChunk().getY(), undos.get(current_spot));  
      Log.sLog("current edit point"+current_spot);
   }
   
   public boolean hasRedo(){
      if(current_spot<undos.size()-1)
         return true;
      return false;
   }
   
   public boolean hasUndo(){
      if(current_spot>0)
         return true;
      return false;
   }
}


ended up copying much less with each edit now, although this limits me it does offer more control over the memory being used. where before it would spike up from 300,000K to 700,000K within a matter of a few edits.(i was copying the entire world needlessly). But again the issue of the memory not being free is still there :/
Offline Kyperbelt

Junior Duke


Medals: 1



« Reply #4 - Posted 2013-11-07 07:51:45 »

I would say make a clearup method that runs through all your code removing dead arrays. What it sounds like is when you call undo you are not clearing up the arrays you have created which just clogs up your memory

i tried this by adding a shred() method to the Xerox interface. every time i remove an item from the list i make a call to it but it did not solve the issue. here is a short code sample of how i coded it.
could be wrong though;

in the tile class
1  
2  
3  
4  
5  
6  
public void shred() {
         for (int i = 0; i < layers.length; i++) {
            layers[i].shred();
         }
      }
     

in the layer class
1  
2  
3  
public void shred() {
         layerdata = null;
      }


i dont know if that would do it. i have also tried different approaches like Arrays.fill(layerdata,null);
and making an Integer[][] array instead of primitive int[][] . but it had little to no effect
Offline philfrei
« Reply #5 - Posted 2013-11-07 08:35:11 »

Just curious, when you multiply out the dimensions of your worlds/layers/regions or whatever, how many [][]'s do you expect to have?

"It's after the end of the world! Don't you know that yet?"
Offline namrog84

JGO Ninja


Medals: 46
Projects: 4


Keep programming!


« Reply #6 - Posted 2013-11-07 08:37:24 »

So in your original code you had undos.add(world.copy());
For every single edit in your addEditPoint function

Thats making a copy of the entire world, for every single change edit?
Even in your edited version where instead you call
undos.add(ed.WM.getCurrentChunk().copy());
you might not be copying the ENTIRE world, but instead now saving only that 1 particular chunk.

But while I don't know what kind of game you are building, l will assume its a 3d world? maybe 2d?  if its a 2d chunk, lets say its 256x256 chunk?  65,536 tiles in that chunk?
Lets say its a 100x100 chunk and so it'd be 10,000 tiles
you are saving 10,000 tiles for every '1 tile' you change?

maybe you should instead save only the '1 tile you changed' a new version and an old version( so you can call undo/redo) and swap only that 1 specific tile.


I think this is the problem.
So after only 10 tile edits, youve saved 100,000 tiles of data.  If a tile is nothing more than an int.
After even a few minutes of edits, you could easily have millions or int saved unnecesaraily, when you should only have saved
number of edits * 2 (old and new)

Right now you have no limit on your undo depth, and because its making so many copies for every single change you have, itll get out of control really really fast.
Alternatively, if you REALLY hate the idea of having saving only a single tile, your original approach with a LinkedList might have been better, if your if logic wasn't broken
This is all you'd need

1  
2  
3  
if(undos.size > 5)
  undos.pop_front();
undos.add_back(world.copy());

(only have undo depth of 5 or some relatively small number)
That way you only ever save 5 instances of your world, or chunk, it was that your original logic and idea was semi correct

"Experience is what you get when you did not get what you wanted"
Offline Kyperbelt

Junior Duke


Medals: 1



« Reply #7 - Posted 2013-11-07 08:40:19 »

Just curious, when you multiply out the dimensions of your worlds/layers/regions or whatever, how many [][]'s do you expect to have?

i expected a lot. and i wasnt surprised at the amount of memory it took , but at the fact that once i "deleted" them the heap size was still tremendous. and gc was not collecting anything.
I scaled the copying down by a lot(to the local chunk being edited) and although i am not getting the ridiculous amounts of memory usage its still not being cleaned out.
Offline Kyperbelt

Junior Duke


Medals: 1



« Reply #8 - Posted 2013-11-07 08:50:27 »

So in your original code you had undos.add(world.copy());
For every single edit in your addEditPoint function

Thats making a copy of the entire world, for every single change edit?
Even in your edited version where instead you call
undos.add(ed.WM.getCurrentChunk().copy());
you might not be copying the ENTIRE world, but instead now saving only that 1 particular chunk.

But while I don't know what kind of game you are building, l will assume its a minecraft 3d world? maybe 2d?  if its a 2d chunk, lets say its 256x256 chunk?  65,536 tiles in that chunk?
Lets say its a 100x100 chunk and so it'd be 10,000 tiles
you are saving 10,000 tiles for every '1 tile' you change?

maybe you should instead save only the '1 tile you changed' a new version and an old version( so you can call undo/redo) and swap only that 1 specific tile.


I think this is the problem.
So after only 10 tile edits, youve saved 100,000 tiles of data.  If a tile is nothing more than an int.
After even a few minutes of edits, you could easily have millions or int saved unnecesaraily, when you should only have saved
number of edits * 2 (old and new)


Alternatively, if you REALLY hate the idea of having saving only a single tile, your original approach with a LinkedList might have been better, if your if logic wasn't broken
This is all you'd need

1  
2  
3  
if(undos.size > 5)
  undos.pop_front();
undos.add_back(world.copy());


That way you only ever save 5 instances of your world, or chunk, it was that your original logic and idea was semi correct

its just a 2d tiled game, 30x30 chunks being loaded with procedural generation but the problem is not the game itself hehe, i am making the map editor. and i agree that i am copying a whole lot.
And yes initially i was only going to have a certain amount of edits available.

i will try to implement undo on a tile by tile basis and see how that works out. it will be harder to manage them that way though hehe.

also what would happen is i would make lets say 10 copies of my world, then i would undo 9 times and then add another editpoint, then everything after the editpoint would be removed. yet the memory usage would stay high even though i just deleted all 8 instances of the world.


thank you for the feedback, ill look into it more after i put my kids to bed
Offline philfrei
« Reply #9 - Posted 2013-11-07 09:02:29 »

Are you using JVisualVM?

I wish I was more skilled with reading profiler data and GC behavior. There's a meet-up in a couple days in San Francisco (nearby for me) on Java profiling. Am hoping to review about the subject beforehand and maybe learn a few things via attending...

I do recall that not all memory being GC'd is equal. Some is more volatile, more quickly recovered than objects that have been around for longer, or if the more volatile GC area experiences overflow into the more stable categories.

Common thing to look for in memory leaks: publishing data variously and not keeping track of all instances. You are probably already watching out for this.

Making your update operations as local as possible sounds like a really good move.

"It's after the end of the world! Don't you know that yet?"
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline xsvenson
« Reply #10 - Posted 2013-11-07 09:14:50 »

Depending on the defined memory limits and also depending on the GC type, the GC reacts only when it thinks it needs to. If You have lots of memory left, the GC can be very lazy and recycle the memory quite seldom. If You put a limit of 2gb then 1.2gb of usage is not much.

“The First Rule of Program Optimization: Don't do it. The Second Rule of Program Optimization (for experts only!): Don't do it yet.” - Michael A. Jackson
Offline theagentd
« Reply #11 - Posted 2013-11-07 12:02:06 »

1. How much memory does your world actually need? If your world is huge then of course copying it a lot will use a lot of memory.
2. I assume you're looking at the memory usage of the java.exe process in the task manager. This is not representative of how much memory Java is using at the moment.

Try to reduce the heap to just barely fit your world copies (plus a little more for everything else of course). If you're not actually running out of memory (OutOfMemoryError) then you don't have a memory leak. You just generate a huge amount of garbage. The VM has a tendency to automatically increases the heap size a lot in such cases.

Myomyomyo.
Offline 65K
« Reply #12 - Posted 2013-11-07 17:43:41 »

Like already written, do not save world copies in the undo manager.
Look up the command pattern. Create command classes for setting and deleting tiles, filling areas, whatever.
Store the affected tiles in each command, give them an undo method, keep a command history in the undo manager. Limit possible undo steps.
Done.  Smiley

Offline StumpyStrust
« Reply #13 - Posted 2013-11-07 17:50:01 »

Not sure if it was mentioned but maybe a profiler? I think it is pure insanity to try and find a slowdown or memory hog without one. I use visual VM and it has saved my ass so many times. Just sample CPU or memory and oh look why are there so many int[]? Then you move on from there.

Offline Kyperbelt

Junior Duke


Medals: 1



« Reply #14 - Posted 2013-11-07 19:29:00 »

@philfrei & @theagenttd
I am using both the windows memory manager and the JvisualJVM
i am also looking at heap dumps and it is where im getting all my data from

Like already written, do not save world copies in the undo manager.
Look up the command pattern. Create command classes for setting and deleting tiles, filling areas, whatever.
Store the affected tiles in each command, give them an undo method, keep a command history in the undo manager. Limit possible undo steps.
Done.  Smiley

Yeah i have come to the conclusion that this is the only way. will need to look into it more in depth. Any resources on this would be appreciated Smiley
Offline Kyperbelt

Junior Duke


Medals: 1



« Reply #15 - Posted 2013-11-07 21:06:10 »

So i have thought about it for a while now and jotted down some ideas and it looks promising.

i will approach this on a command by command basis as suggested above. It will take a bit of re-coding but it should be too hard and it will eliminate all unnecessary copying of unchanged tiles/chunks ect.

Each time an edit is made a new command object for the specific action being done will be made;
changes will be added to said command object.
and when the edit is done, said object will be added to the UndoManager.
while there the undo manager will use the command hatch() or kill() methods to either undo/redo an edit.

But yeah seems i was creating too much garbage too fast for the gc.

Thanks for all the help everyone.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

Longarmx (34 views)
2014-10-17 03:59:02

Norakomi (25 views)
2014-10-16 15:22:06

Norakomi (24 views)
2014-10-16 15:20:20

lcass (26 views)
2014-10-15 16:18:58

TehJavaDev (50 views)
2014-10-14 00:39:48

TehJavaDev (50 views)
2014-10-14 00:35:47

TehJavaDev (40 views)
2014-10-14 00:32:37

BurntPizza (63 views)
2014-10-11 23:24:42

BurntPizza (36 views)
2014-10-11 23:10:45

BurntPizza (74 views)
2014-10-11 22:30:10
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!