Mediatracker peaks my RAM usage alot!.

My game uses ~400 megabyte in all. When game starts I have a nice loading screen with a progress bar (which I update) and game load all arts using a mediatracker. The arts are png’s.

However, the peak RAM consumption is 750-800 Megabyte so that means even on 1 GB machines it can force swapping and this means very inconsistent and sometimes VERY slow loading time of the game.

The problem is, even if I make small portions of the art as in

readImages()
readImages2()
readImages3()

and let each one of those methods do WaitForAll the RAM returns very slowly to the System so when i get to that last method I am gonna get to the 800 MB usage spike.

Seemingly if I run the game again the System Cache will make it run faster but this only makes it worse for me since I need to reboot the system to get the “real deal loading time” again.
I have tried using System.gc() mid way through the “readimage” methods to return RAM so that I can avoid the spike but it does not work.

  1. Is there a way to disbale System cache on XP?

  2. Is there a way of avoiding this huge RAM spike by returning whatever memory being used to decompress a png or whatever the reason for the spike is?

  3. Is it better to use waitforall at several locations or just add all arts and then to a final large waitforall?

  4. Is there any difference using several mediatrackers loaded a small chunk each or use just one?

MediaTracker is obsolete.

Have a look at the javax.imageio package, in particular ImageIO, ImageReader and IIOReadProgressListener.

Thanks :slight_smile:
By the way, I am using Java 1.4

There does not seem to be much code or tutorial for using the ImageReader out there so any help would be welcome. I just do not know where to start.

ImageIO.setUseCache(false);

Turning that off saves some ram.

However, with that much amount of image data I would take a look at opengl bindings and DXTn compression. It’s faster to load than everything else and it only takes 1/4 or 1/6 of the vram.

But I do not use openGL for drawing in my game so I guess I cannot use any openGL bindings then? I use pure swing. It is a turn based strategy game so I have decided I did not need any great framerate hence no need for OpenGL.

Yes, it’s not an option then.

The problem as I see it is that the 400 MB used by my game and the 800 Mb peak leaves 800-400=400 Mb of RAM that I cannot free up instead it seems Windows reutnr about 1 Megabyte per 3 seconds so it will take ages before that RAM is available.

If I only could

readImages();
giveBackRAM();

readImages2();
giveBackRAM();

readImages3();
giveBackRAM();

then I would get my peak much lower.

I also read somewhere that reading PNG’s is not supported until Java 1.5 and I am using 1.4 so it seems very crazy that I would need to switch my whole environment just to fix a temporary memory shortage that only take place once while loading game :frowning:

I also read somewhere that reading PNG’s is not supported until Java 1.5 […]

Naah. Loading PNGs is fine with 1.4.x. Just wrap it up with a BufferedInputStream to work around some 1.4.1 glitch and that’s it.

See this example:
http://kaioa.com/k/jarimage.jar (doubleclickable, source included)

I checked the test.java

and the following code

img=ImageIO.read(new BufferedInputStream(getClass().getResourceAsStream("/bar/trisk.png")));

and replaced the “/bar/trisk.png” witt the path to my image

It did not preread my huge images that I need to be preloading before game starts. I did not draw the buffered image though, just created it, would that make any difference?.

Is this code the same as using

mediaTracker.addImage(blablabla, 0);
mediaTracker.waitForAll();

??
For me it did not preload the image to RAM

Edit:
In fact, the BufferedImage was never created becauase I tried makeing a img.getWidth() call which caused nullpointerexception

if getClass().getResource(yourPath) is null, the path was wrong.

I got the path working but the image is apparently not being recognised when I later make a call to

Toolkit.getDefaultToolkit().getImage(

Does this mean I need to make use of the bufferedimage I just created or else it will have no reference by the game?

Does this mean I need to make use of the bufferedimage I just created or else it will have no reference by the game?

Yes.

You can for example put em in a hashmap at the beginning and retrieve the references from there wherever you need it.

I tried storing the bufferedimage in a Vector just for keeping it referenced hence so that it stays in RAM… but it did not work!
I checked the buffered image and its width and heigh was correct so apparently it had loaded.

But why would it be necessary to keep the references? With mediatracker all I did was load the images and they were in the RAM. If I later made a getImage(some parameters) and that image was one of those I had already in RAM it automatically used it, as should be?

So, Images that lose reference are not still in RAM? ::slight_smile:

When I tried painting the map from a getImage call in my MapCanvas class it was not preloaded obviously so it took alot of time before it was showing.

My point is, if i store a map.png somewhere in my game I do not need to reference it i can instead use Toolkit.getDefaultToolkit().getImage(somepath/map.png).

and the software should know it is already in RAM. This did not seem to work :frowning:

Is there something special about bufferedimages so in that case can i “paint” a buffered image into RAM so that it stays there. Boy, I am getting confused now…

Hi! I’ve been facing that problem for a little while: Images did not get to load BEFORE I call getImage(). So at that point I tried to use the MediaTracker, as usual. It seems that you have to load every kind of Images with this MediaTracker connected to them. As long as the Image keeps stacktrace in RAM, its data won’t be garbage collected but if it is a VolatileImage, contents can be lost in any time of code execution. So you should check if the load-get-store scheme in your program is correct:


class ImageScreen extends JComponent {
   int id = 0;
   Image im = new BufferedImage(Toolkit.getDefaultToolkit().createImage(), 150, 150);
   MediaTracker mt = new MediaTracker(this);

public ImageScreen() {
   super();
   // do some additional drawings
   im.getGraphics().fillRect(0,0,im.getWidth(), im.getHeight());
   // immediately following:
   mt.add(im, id);
}

public void paintCoponent(Graphics g) {
    try { mt.waitForID(id); } catch (InterruptedException e) { e.printStackTrace(); }
    // finally you can surely get the Image to show 
    finally { g.drawImage(im, 0, 0, this); }
}
}

:wink:

But do I then not get my inital problem back that the MediaTracker uses loads of RAM in its loading process?
The excess usage of RAM that the MediaTracker is responsible of seem to go outside the game and instead be system RAM (maybe because it decompresses png’s ?) and it only returns it at a slow rate of 1 meg per 3 seconds. This means if I start the game and click around there will be alot of arts loaded from time to time and the excessive RAM usage will be away for a while so it will be swapping.

So, if the game is of the nature that you stumble across most of its arts in the first 3 minutes of the game then the RAM will run out and start swapping.

If a huge map takes 10 second to load then it would mean I get this delay the first time i want to draw it instead of having all the waiting while my loading screen is shown on game statup.

Sorry if this was answered already, but what kinds of images are you loading where the game actually needs this much RAM? I can’t even fathom what these could be, particularly for a TBS strategy game.

If you really need all these images loaded at once, then seriously consider moving over to OpenGL and loading in DXTn compressed textures (also known as S3TC), which really do take up far less VRAM.

That is correct but as you can read the code beyond, it can be loaded before you call display. So it is that you can expect a delay between init and show.
But the other way to avoid high use of RAM could be that you load only one FileChannelInputStream brought by the JAI ImageIO lib. Thus it is faster at loading. But it still doesn’t let you ignore pre-loading of data. As well as it cannot be checked if data are lost without VolatileImage Objects.

That is one reason for I’m making out of a simple RAM self-made swapper, I mean, to put all data to a disk swap file list as I clear the memory to garbage. I use java.lang.ref SoftReference (commonly Soft-Cache) and PhantomReference (Buffer) plus java.io.File to swap Objects to file system. it really speeds up RAM and I managed to catch all Overflows through methods callbacks.

In fact, once loaded, BufferedImage will be stored in RAM. So if memory heap limit isn’t overrunned, then to draw ain’t problematic for the JVM. My thoughts about overrunning memory brought me to consider every java method-call to grant them Thread-safe operations as well as to avoid OutOfMemory exception loops. ;D
you can see that stuff at Koders or in my own project sf3jswing.cvs.sourceforge.net about SoftCache in Java

The “toolkit image loading”, which includes MediaTracker, does a lot of copying data
around. You can try using ImageIO for loading and see if it works better.
However, in 1.4 ImageIO was not in the best shape…

Dmitri

MediaTracker doesn’t copy data at all, I think it should be used with caution though, but it is really the most simply way to check for loading on pics used simultaneously with ImageIO.Toolkit. Acceleration can be improved with some simple JVM arg options like sun.java2d.* and other OpenGL tweaks, as well as you can setAcceleration() for each images if you try JAI + JIIO image tools -> http://java.sun.com/javase/technologies/desktop/media/