0

I have a 2D map in this format: (x,y,type,index) Which is fed into jmonkeyengine renderer from a Swing app. I used:

String map_array[10000][1000];

Example:

map_array[100][200]="E8";

Which means in position x=100 and y=200 there is an Enemy ("E") with index of 8. Its memory behavior is like this:

Memory of String array

and in another way I made:

byte map_array[10000][1000][2];

Example:

map_array[100][200][0]='E';
map_array[100][200][1]='8';

Which has the same meaning of above example. Its memory behavior is like this:

Memory of byte

My questions are:

  1. Why String has strange behavior of slow allocating and bounces (as you can see it gets more than 2 minutes to reach maximum though the game is running smoothly)?
  2. Byte method seems to be less memory consuming but which way is better?
RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • How do you create and assign the values in the first method? Do you create new strings and put them in it, or do you use the old strings and move them around? – RealSkeptic Oct 12 '15 at 19:10
  • I use "new" expression only once in constructor. But in renderer loop I just set all array values to "0" for String and then attach none move able area like String[10][20]="F1",String[20][40]="F2" ,... and then assign characters locations like in example then but also for enemies I use local refresh it means if enemy location was close to camera assign its location to main map_array. and this process repeats. in bytes i just use '0' and 'F' , 'E' and '4' instead of "0" and "F2" , "E4". –  Oct 12 '15 at 19:15
  • what does the pink and purple areas mean? – hevi Oct 13 '15 at 14:19
  • Sorry yea I had to describe images. pink is total heap space and purple is used heap space. –  Oct 13 '15 at 16:02

1 Answers1

1

Your first declaration String map_array[10000][1000] creates an array of arrays with pointers to String objects. In Java the Strings are

  1. Immutable: Each time you change a String, a new Object is created on the heap.
  2. Interned: Two Strings which were defined by the same string literal automatically share the same underlying char[] (a = "F1"; b = "F1"; a and b share "F1"). This can save memory. But once a char[] is not used anymore, it remains in the cache for string literals.

I can't tell what exactly causes the memory fluctuations without knowing what the program does during that time. But my guess is it has to do with those things mentioned above and the Garbage Collector.

You can avoid unnecessary allocations by reusing the same constant String object:

static final String F1 = "F1";
map_array[10][20] = F1;
map_array[20][40] = F1;

The second declaration byte map_array[10000][1000][2] creates an array of arrays of arrays. No magic going on and no overhead of memory allocation to change values.


Your map_array looks like it's very sparsely populated. Is there a reason for representing every single field on the map? If so, can't you use a HashMap which only stores the fields in use?
Why even store anything when the jMonkeyEngine already stores object type and position in its Scenegraph Nodes?

1000ml
  • 864
  • 6
  • 14
  • 1
    Your statement about interning is not correct. Java does not automatically intern _all_ Strings. it only automatically interns constant Strings (those written directly in your code). – jtahlborn Oct 13 '15 at 14:28
  • @jtahlborn Thanks, I changed that. – 1000ml Oct 13 '15 at 14:52
  • "Each time you change a String, a new Object is created on the heap." this means changing only one element of String[][] makes a new String[][] or makes a new String on that only one element. If it makes new String[][] then I got the answer and it should bounce on memory! Is that true? Jmonkeyengine is almost irrelevant because I only use its renderer part which is a port to OpenGL the reason is that I wanted to use java but it can be converted to C++ or any other language because there is no dependency on jmonkeyengine builtin methods. Even I manually calculate vertices, textures, indexes, .. –  Oct 13 '15 at 16:13
  • @Amir `map_array[10][20] = "F1"` only creates one new String object and changes the pointer in `map_array[10][20]`. The old object however is kept in memory until the GC removes it. If you frequently change strings you rapidly increase the number of objects until the GC frees them. This _could_ lead to the memory spikes you're seeing. I'd try to reuse the strings like in my example in the answer and see if that changes something. – 1000ml Oct 13 '15 at 16:24
  • Yes you are right as I changed "temporal coherence" accuracy, domain and frequency of peaks change. slow "temporal coherence" causes lower peaks and bounces and More fps and string change cause more bounces.And gradual convergence in about 3 min is caused by GC getting lazy! I can change memory behave by force GC! Thanks –  Oct 13 '15 at 16:45