VASSAL hotspots

When I have a map open, CPU is running at about 30%.

The big hotspots are MappedDataBufferByte.getElem(int,int) and MappedDataBufferByte.setElem(int,int,int). No interaction is occurring. Any suggestions?

  • M.

Thus spake “mkiefte”:

If it’s just sitting there, there shouldn’t be any repaints happening at
all. I’ll have to look into that.

Also, turn off memory-mapped files for images and try it without that.


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

It appears to be even more complicated. This only happens on one
computer: my laptop.

Has anyone observed high CPU usage when VASSAL does nothing? It
always shows Java running at 30% per open map. Open three maps and it
grinds to a halt.

Astoundingly, the Diplomacy module on the VASSAL website grinds it to
a halt right away.

The short of it is: I don’t think this is VASSAL’s problem. Is it
possible that Xorg is constantly trying to refresh the map causing
getElem to be called? I can’t believe I’ve wasted this much time on
this problem…

  • M.

On 13/02/2008, Joel Uckelman uckelman@nomic.net wrote:


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake “Michael Kiefte”:

Hmm. I don’t recall having seen that before—I think I would have
noticed the last time I did profiling. Maybe you have a crap video
driver, and it’s causing more repaints than is necessary?


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

I’m still working away at this problem.

What I’ve discovered is that there is a problem on several computers.
Some computers are just so powerful that you don’t notice a problem.
My laptop is obviously not as powerful.

Map.View.paint() is being called repeatedly with new Graphics objects
each time. This never stops. There is occasionally a pause for
garbage collection. System.out.println(r) gives the same rectangle
each time. It is being called in response to a
RepaintManager.paintDirtyRegions() request.

There was a problem with an xorg-server upgrade and Java some days
ago. I downgraded but observed no difference.

Why does the RepaintManager think the mapboard is always dirty? Can
someone try this on a Windows computer? Can someone else with a Linux
box try this? My computer at work is a quad and you just don’t notice
this happening until you do a System.out.println().

  • M.

Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Okay, I have a stack trace of this repeated call:

Thread [Image Animator 3] (Suspended (breakpoint at line 2442 in Map$View))
Map$View.repaint(long, int, int, int, int) line: 2442
Map$View(Component).imageUpdate(Image, int, int, int, int,
int) line: 2939
ImageWatched$WeakLink.newInfo(Image, int, int, int, int, int) line: 114
ImageRepresentation(ImageWatched).newInfo(Image, int, int,
int, int, int) line: 151
ImageRepresentation.imageComplete(int) line: 639
GifImageDecoder(ImageDecoder).imageComplete(int, boolean) line: 135
GifFrame.dispose() line: 617
GifImageDecoder.readImage(boolean, int, int) line: 439
GifImageDecoder.produceImage() line: 195
URLImageSource(InputStreamImageSource).doFetch() line: 246
ImageFetcher.fetchloop() line: 172
ImageFetcher.run() line: 136

Map$View.repaint is a method I just wrote for debugging output which
is actually just a call to super.repaint(long, int, int, int, int) and
some output code.

This call is repeated without end.

The second argument to
GifImageDecoder(ImageDecoder).ImageComplete(int, boolean) is always
false.

The only GIF images in this module are the builtin images are GIFs,
e.g., moved.gif. I’ve tried eliminating those, but there’s no change.

  • M.

Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake “Michael Kiefte”:

Huh, I wonder if the spinners for loading tiles aren’t stopping once
the tiles are drawn. I think I know how to solve the problem now. Thanks.


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Looks like you may be right. The URL it is repeatedly trying to read
is roller.gif. Sorry I didn’t discover that sooner.

  • M.

On 14/02/2008, Joel Uckelman uckelman@nomic.net wrote:


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Excellent catch!

rk

Post generated using Mail2Forum (mail2forum.com)

On 14/02/2008, Rodney Kinney rodneykinney@comcast.net wrote:

Let’s hope that’s it! Joel’s graphics code is very deep – very
nicely done by the way – so I’ll leave it to him to see if that’s
were the problem is.

Nevertheless, there were two factors involved in finding this: the map
in question was roughly 4000x4000 and the laptop was woefully
underpowered. You just don’t notice this on a half-decent desktop or
with a much smaller map.

All this work to speed up VASSAL on my laptop… (which is where I’ll
be doing all my gaming anyway :slight_smile:

  • M.

Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Interesting link:
bugs.sun.com/bugdatabase/view_bu … id=4216579

The solution appears to be to have a separate image observer keep
track of the roller then have it return false when the other images
are loaded. That should kill it.

What do you think? Joel, I’ll leave this one to you. I don’t want to
mess with your graphics code and I don’t know Java graphics very well.

  • M.

Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Correction: this looks more complicated than it seems. How do you
know when all the tiles are loaded? If you scroll the window, more
images need to be loaded, the roller has to start again, etc…

I’m backing away slowly now.

  • M.

On 14/02/2008, Michael Kiefte mkiefte@dal.ca wrote:


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake “Michael Kiefte”:

Yes… this is not simple to fix. I think what has to happen is that
an ImageObserver is created for each unavailable tile, and said
ImageObserver is killed when its tile is finally drawn.

I’m feeling to scattered right not to tackle this one properly—I think
it will have to wait until tomorrow.


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

May I suggest that until a fix is developed, that roller.gif not be
loaded? I agree that a solution is feasible, but in the meantime, can
we treat it as a TODO item and not draw an animated GIF for now?

You mean that ImageObserver.updateImage has to return false when the
tile is finally drawn. In addition to that, the roller cannot be
drawn until it is actually visible, otherwise, it will still be
animated whether it is onscreen or not. I’m seeing repaint calls on
the entire map, not necessarily on the visible portion.

I understand completely. If you think it will be fixed within a short
while, desregard the first paragraph above. However, an easy fix is
to simply not draw roller.gif. If you leave it out, performance jumps
dramatically on my wimpy laptop.

It would appear that, while Java is relatively smart about drawing
animated GIFs without any additional thought on the part of the
programmer, there really isn’t really an API for controlling them.

  • M.

Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake “Michael Kiefte”:

I thought of how to fix this as I was falling asleep last night:

Every time a tile is requested asynchronously, we already create an
ImageOpObserver which will be called when the tile is loaded. Board
uses the Repainter implementation of ImageOpObserver, which keeps a
reference to the Map.View and Rectangle to be repainted. We could
extend Repainter to implement ImageObserver also. The point at which
the spinner for a tile should be started is when ImageOp.getFutureTile()
tells us that the Future isn’t now. Since we have to make that call
with the Repainter as an argument, we still have it, and so can pass
it to Graphics.drawImage as the ImageObserver for the roller. That
takes care of starting the rollers.

For stopping the rollers, we want to do that when loading the tile is
complete (there’s no noticeable time between when a tile finishes
loading and when it’s painted if it’s on screen). Because it
implements ImageOpObserver, Repainter already has a method which is
called when its observed tile is ready: imageOpChange(). What we do is
add a member boolean opComplete which is set true when imageOpChange()
is called. Then, in addition to doing whatever else it needs to do to
animate the roller, we have imageUpdate() (from the ImageObserver
interface) return the value of !opComplete. This way, imageUpdate()
returns true iff the roller should continue drawing frames.

I think that would solve the problem.


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

This sounds like it will work but you really ought not to lose sleep over it!

  • M.

Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake “Michael Kiefte”:

I always think about things like this as I’m falling asleep. :slight_smile:


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake Joel Uckelman:

Here’s a partial fix, in 3.1.0-svn3088:

nomic.net/~uckelman/tmp/vassal/

It’s only a partial fix, because the roller associated with each
TileRepainter is only stopped when the TileRepainter is garbage
collected. When I run this in the profiler, I have approximately
10% CPU sitting idle, but then when I force garbage collection,
it drops to 0% on idle until the next time some more rollers are
shown.

Still, this is better than before.


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

It does what you say below. I’m right now watching my CPU monitor run
at 30%, though. The garbage collector has run once, but then I
zoomed, and it went back up to 30% again. It takes a long time for GC
to kick in if you just watch. I have a slow CPU but my java stack is
756 Mb, so this could take a while…

Can you use the same ImageObserver for the tile and roller in each
block and return false to all calls to ImageUpdate when you know the
tile is finished? or is it impossible to know that the tile is
finished?

  • M.

On 15/02/2008, Joel Uckelman uckelman@nomic.net wrote:


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake “Michael Kiefte”:

I switched it to do that. I think this fixes the problem, in 3094:

nomic.net/~uckelman/tmp/vassal/


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)