Avoiding creation of Color object

Hi,

I have a small Applet, where I draw some stuff using g.drawLine(…) (g is a java.awt.Graphic object). I have to draw huge amounts of line, and depending of their position, a Color is chosen -> Everytime I draw a Line, a g.setColor(…) is called, with the desired Color.

First problem : As I have about 40 000+ lines, about 40 000 (!) Colors are created at every repaint.

What I want to do, is to create a single Color Object, and then change it’s RGB values, avoiding a Constructor call. Example :


c.red = something;
c.green = something;
c.blue = something;
g.setColor(c);

or


c.setRGB(something);
c.setColor(c);

This would save me a lot of memory space, and will be faster (Object creation is too slow in this case, compared to simple field assignation).

Second problem : the java.awt.Color class does not have methods like setRed(int), setGreen, setBlue, there are no r, g, and b public fields.

I then wanted to subclass Color, in order to implement some methods to change the color value.

Third problem : The color value is stored in a private int field, which means that I can’t change it outside of Color… I can’t subclass Color, in order to implement my own setRGB method. The only way to change the color Value in a Color object is to recreat a Color object.

My question : Am I right ? Is there no way to change a color value without creating a new Color object ? Is there a way to do what I want ?

Thanks !

I believe what you’re saying is java.awt.Color is non-mutable, which is true. If there are only a small number of colours you actually use keep them an instance variables instead of local.

If there are loads of colours you could implement some sort of ColorCache object which lets you request a colour specified by its red green and blue components. If its not in the cache, its created, added to the cache and returned. If its already in the cache then you just return your copy (preventing the construction).

Kev

Kev is correct. Color is an immutable object, like String or Integer. You can’t change it. The idea being that “red” is “red” and “red” cannot become “blue”. You can change the colour of something to a DIFFERENT colour, but the same colour object must always be a specific colour. E.g. the Color.RED static member of the Color class would be useless if you could just redefine it to come out green instead.

More importantly, have you profiled your code to determine that it actually is the construction of Color objects that is the bottleneck? If not, do that first. If it is the bottleneck then maybe try an object cache as kev suggests.

For quick testing… just create one Color object and use it all the time. See if it makes a difference.

If so you could try 12bit colors - 4096 colors in total. Getting those ramps is rather easy:


for(int r=0;r<16;r++)
  {
   for(int g=0;g<16;g++)
   {
    for(int b=0;b<16;b++)
    {
     there you go -> new Color(r*17,g*17,b*17);
    }
   }
  } 

I’ve checked my code using JProfiler. The construction of the Color Objects is the Bottleneck of my drawing method. I’ve optimized the whole method (some calculation is performed), and the Color constructor is the last thing which cause a performance decrease.

I’ve tried to put a static color, as you say, and I’ve got a 20-30% decrease in execution time. Moreover, all of these Colors eat my memory : at certain moment (if JProfiler says right), up to 10Mb of RAM is chewed up by Color objects…

As all of you say, I think I’m gonna create a color table with pre-calculated colors, although it don’t please me (that’s a lot of objects storing…) :slight_smile:

Try the following code:


import java.lang.reflect.*;

      public static void setColor(Color colour, int rgb) {
            try {
                  Field f = colour.getClass().getDeclaredField("value");
                  f.setAccessible(true);
                  f.setInt(colour, rgb);
            } catch (IllegalAccessException ex) {
            } catch (IllegalArgumentException ex) {
            } catch (SecurityException ex) {
            } catch (NoSuchFieldException ex) {
            }
      }

Since it uses Reflection, you may have to sign your Applet, not sure…

Better yet, would be to cache the Color object, and the “value” declared field, then all you need to do is change the value of the cached field and re-use the color object.

Hope this helps,
Doron

You should profile it, but using reflection is more than likely going to be slower than just creating the appropriate objects.

It really is a inventive/hideous thing to do though. :wink:

Kev

[quote]Try the following code:


import java.lang.reflect.*;

     [...]

Since it uses Reflection, you may have to sign your Applet, not sure…

Better yet, would be to cache the Color object, and the “value” declared field, then all you need to do is change the value of the cached field and re-use the color object.

Hope this helps,
Doron
[/quote]
Great ! I’ll give a try to this.

And signing the Applet is not a problem, as it is already signed (need to access a data file located on a CD-ROM).

LeCastor, What java version are you using?

I find it unlikely that the creation of Color objects would be the bottleneck in your app in any recent vm.

It’s a very lightweight object, and it’s creation is very cheap for the vm - especially in comparison in rendering line - there’s way more objects being created during that process.

To test this you don’t even need a profiler: try this, instead of creating a new Color object every time, use something like


Color colors[] = {Color.red, Color.green, Color.blue };
int colorNum = 0;

and in your rendring loop use this instead of creating
a new color.


setColor(colors[colorNum++ % colors.length);

(the use of several colors instead of just one is to
emulate the pipeline revalidation when the color is changed, otherwise it won’t be a fair comparison)

[quote]You should profile it, but using reflection is more than likely going to be slower than just creating the appropriate objects.

It really is a inventive/hideous thing to do though. :wink:

Kev
[/quote]
Profiling ANYTHING you create is a good idea before production stage, but even though Reflection has a bad name for being “slow” it still may surprise you.

Consider what would happen if a method using Reflection is JITed, wouldn’t that provide almost the same speed as “natively” performing the same action through non-Reflection code?

But it’s not a question of being jitted or not, the operation itself can be much more costly - like, it could take some global lock. No jitting would help that.

Also, believe me, you don’t want to change the values of already created Color object. If it was built to be immutable, you don’t know what assumptions our implementation makes, you may run into some tricky issues.

[quote]But it’s not a question of being jitted or not, the operation itself can be much more costly - like, it could take some global lock. No jitting would help that.

Also, believe me, you don’t want to change the values of already created Color object. If it was built to be immutable, you don’t know what assumptions our implementation makes, you may run into some tricky issues.
[/quote]
I’m not sure, but I don’t think that Reflection is built the way you describe it, this probably necessitates a quick look in Sun’s sources? :wink:

Also, sometimes, there’s just no choice, believe me when I say that library-developers don’t always come up with the max usage of their libraries. Sometimes, you have to inherit something just to expose parts that have been left private cause that’s what your Client actually needs. (Last sentence wasn’t from the perspective of a game programmer)

True enough, but any time you do that you’re taking the risk the library developer has made assumptions based on their protection of member variables.

Using reflection to get at um is just evil tho :wink:

Kev

Actually, in the case of Color object I can guarantee that you’ll break a lot of stuff by making it mutable, and thus breaking the contract. Our code relies on the fact that it’s immutable, so there are places where we cache the currently set color, and check if the new color is the same object as the old one, and do not modify some structures if it is.

BTW, I’m still not convinced that it’s the creation of the Color object is the bottleneck in your app…

I know ;). Actually, it is the last time-consuming operation in my drawing routine. Every other operations consist of simple calculation. The problem of creation of Color object, is that it creates too much objects in memory, as many are created within a small amount of time (which means if don’t get garbage collected immediately, and when it has to be, zillions of objects are collected).

I had the small problem with another program. It was a 6-DOF 3D camera system, using Quaternion. The program was slow. I profiled it, and realised that 200 000+ Quaternions were created each 5 secondes :o… I changed the way i was doing my operation, with just one Quaternion created at camera creation, re-using the same one everytime. Result, 50% + speed increase. Believe me or not.

Same goes here. Lots of lines are drawed in a small amount of time. Which means lots of time in spent in Color object creation, memory allocation, field assignation, etc… It is still slower than just change the value itself.

I agree, a Color object is immutable. But I don’t really care about programming philosophy here. All I want is to store a Color value somewhere, without having to recreate an object everytime. All of you know (or should know :wink: ) it’s bad to create 20000 objects per second.

Could you post some example code that illustrates the problem? Maybe we can find alternatives or at least better understand what is happening.

[quote]True enough, but any time you do that you’re taking the risk the library developer has made assumptions based on their protection of member variables.

Using reflection to get at um is just evil tho :wink:

Kev
[/quote]
It may be evil, but so is hiding stuff you absolutely have to expose cause there’s no other way to accomplish a desired functionality. I’ve had the same problem with some classes in the Delphi Component Libraries once, there was no choice but to subclass and re-expose things that were hidden.

Also, it has occured to me that caching the Color object and its “value” Field may speed things up a notch cause you wouldn’t be searching for the Field and setting its access flag every time you’d want to change the colour-value! :slight_smile:

Another thing, where would Java’s Serialization, RMI and plug&play Java-Bean-Box model be without Reflection? :wink:

[quote]All of you know (or should know :wink: ) it’s bad to create 20000 objects per second.
[/quote]
I think this code is better:

import java.awt.Color;
import java.awt.color.ColorSpace;
import java.lang.reflect.*;

public class Colour extends Color {
      private Field cachedColourValueField;

      private void cacheColorField() {
            try {
                  cachedColourValueField = getClass().getDeclaredField("value");
                  cachedColourValueField.setAccessible(true);
            } catch (NoSuchFieldException ex) {
            }
      }

      public void setRGB(int rgb) {
            if (cachedColourValueField != null) {
                  try {
                        cachedColourValueField.setInt(this, rgb);
                  } catch (IllegalAccessException ex) {
                  }
            }
      }

      public Colour(int r, int g, int b) {
            super(r, g, b);
            cacheColorField();
      }

      public Colour(int r, int g, int b, int a) {
            super(r, g, b, a);
            cacheColorField();
      }

      public Colour(int rgb) {
            super(rgb);
            cacheColorField();
      }

      public Colour(int rgba, boolean hasalpha) {
            super(rgba, hasalpha);
            cacheColorField();
      }

      public Colour(float r, float g, float b) {
            super(r, g, b);
            cacheColorField();
      }

      public Colour(float r, float g, float b, float a) {
            super(r, g, b, a);
            cacheColorField();
      }

      public Colour(ColorSpace cspace, float[] components, float alpha) {
            super(cspace, components, alpha);
            cacheColorField();
      }
}

This is sort of a compromise which keeps the “dirty-work” done in the appropriate class “Colour”, letting you have the setRGB(…) method and still claim you’re using a proper Color object :wink:

I would also like to add – and it may seem evil to some – that the only time you’re actually using a Color object is when you’re painting with it, and then, and only then would its RGB value have to be unmutable, isn’t that right? :slight_smile:

I find it very, very hard to believe there was a good reason for making Color immutable, and harder to believe still that anyone could think that creating millions of the buggers wasn’t going to cause a major performance drain in a rendering loop even with a garbage collector written by God himself and all his little wizards.

Cas :slight_smile:

Seems reasonable to me. Not that I don’t see that there are cases for not having it immutable. But immutable objects allow for optimizations just as mutable ones do.

Now in the specific case of a Color object… yeah maybe you are right, since ultimately the optimizations that Trembovetski speaks of could be a simple compare or the 32 bit Color ref, or the 32 bit value of the RGB data. In fact in the latter the code would be optimized to not trigger changes for different Color objects that actually referred to the same colour values. The optimizations could be written to handle both cases. First check the Color ref, if it is different check the value to be sure reseting the graphics pipeline is going to be worth it.

I guess it is just the cost of an extra pointer dereference to get at the value. unless you totally throw out type safety and use ‘int’ for colors instead.