Skip to main content

AbstractPainter cache management

5 replies [Last post]
headw01
Offline
Joined: 2005-05-13
Points: 0

I would like to suggest that the AbstractPainter keep it's BufferedImage that it has already created if the cache.height and cache.width still match the height and width passed into the 'paint(...)' method.

While doing some profiling of my application, I noticed that an awful lot of time was spent in the 'GraphicsUtilities.createCompatibleTranslucentImage(width, height)' method. I was able to eliminate this extra time by keeping the image (even when the cache was cleared... needed a 'cacheCleared' flag).

I have been testing this, and it is working well.

Again, I have an updated version of the AbstractPainter class that has all of the necessary changes. If this seems like a good idea (I think it is), I will supply all of these changes. Not sure what the best way to do that is.

Thanks,
Bill.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
headw01
Offline
Joined: 2005-05-13
Points: 0

Yes, I left the BufferedImage in the SoftReference that was already being used. I didn't use a strong reference to the Image (as a field on the class) though. I made a 'private boolean cacheCleared' field which is set to true in the 'clearCache()' method.

The 'paint(...)' method is changed to use this flag as well instead of just a null image:
(clippings from the modified 'paint(...) method).
[code]

...
BufferedImage cache = cachedImage == null ? null : cachedImage.get();
boolean invalidImageSize = null == cache ||
cache.getWidth() != width ||
cache.getHeight() != height;

if (cacheCleared || invalidImageSize || isDirty()) {
//rebuild the cacheable. I do this both if a cacheable is needed, and if any
//filters exist. I only *save* the resulting image if caching is turned on
if (invalidImageSize) {
cache = GraphicsUtilities.createCompatibleTranslucentImage(width, height);
}
Graphics2D gfx = cache.createGraphics();
gfx.setClip(0, 0, width, height);

if (!invalidImageSize) {
// If we are doing a repaint, but we didn't have to
// recreate the image, we need to clear it back
// to a fully transparent background.
Composite composite = gfx.getComposite();
gfx.setComposite(AlphaComposite.Clear);
gfx.fillRect(0, 0, width, height);
gfx.setComposite(composite);
}

...
//only save the temporary image as the cacheable if I'm caching
if (shouldUseCache()) {
cachedImage = new SoftReference(cache);
cacheCleared = false;
}
}

...
[/code]

Bill.

headw01
Offline
Joined: 2005-05-13
Points: 0

There doesn't seem to be a 'Painter' subcomponent in the Issue Tracker. I was just going to put it into 'Misc' I guess. Also, who should I assign this to?

Bill.

Romain GUY

It is an extremely good idea and, in fact, a good practice. As long
as you properly clear the image content, everything should be just fine.

On May 31, 2007, at 9:46 AM, jdnc-interest@javadesktop.org wrote:

> I would like to suggest that the AbstractPainter keep it's
> BufferedImage that it has already created if the cache.height and
> cache.width still match the height and width passed into the 'paint
> (...)' method.
>
> While doing some profiling of my application, I noticed that an
> awful lot of time was spent in the
> 'GraphicsUtilities.createCompatibleTranslucentImage(width, height)'
> method. I was able to eliminate this extra time by keeping the
> image (even when the cache was cleared... needed a 'cacheCleared'
> flag).
>
> I have been testing this, and it is working well.
>
> Again, I have an updated version of the AbstractPainter class that
> has all of the necessary changes. If this seems like a good idea
> (I think it is), I will supply all of these changes. Not sure what
> the best way to do that is.
>
>
> Thanks,
> Bill.
> [Message sent by forum member 'headw01' (headw01)]
>
> http://forums.java.net/jive/thread.jspa?messageID=219736
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
> For additional commands, e-mail: jdnc-help@jdnc.dev.java.net
>

--
Romain GUY
http://www.curious-creature.org
http://www.progx.org

---------------------------------------------------------------------
To unsubscribe, e-mail: jdnc-unsubscribe@jdnc.dev.java.net
For additional commands, e-mail: jdnc-help@jdnc.dev.java.net

rbair
Offline
Joined: 2003-07-08
Points: 0

> Again, I have an updated version of the
> AbstractPainter class that has all of the necessary
> changes. If this seems like a good idea (I think it
> is), I will supply all of these changes. Not sure
> what the best way to do that is.

Sounds like a reasonably good idea. If we take this approach then we definitely need to store the image in a SoftReference so that the memory can be free'd if resources become tight. Which suggests using two fields, one which is a strong reference to the cache, and one which is a SoftReference, which would be set if the cache is cleared.

Another solution would be to use VolatileImage for the cache, but we can't do that very efficiently if filters are applied, since there isn't a VolatileImageOp. Shame.

The first step I think would be to file a bug so we can track this. Can you do that?

Thanks
Richard

headw01
Offline
Joined: 2005-05-13
Points: 0

Sure, I'll open that up (as an 'Enhancement' since nothing is really broken).

Bill.