Optimizing garbage collection in Processing question(s)?

A couple of years ago, I wrote a decent paint program in processing that works fine with smallish to medium images ( say 1200 x 1200 pixels). Now I'm trying to improve it work with large images (4800 x 6000) pixels. I found how to set up processing to have the memory to work with these larger images, but the problem I'm facing now is with garbage collection.

Things were working fine, but the program was stuttering at sporadic times. I use Windows 7 and pulled up the performance manager. During the stuttering ( 1 second or more), the CPU usage was in excess of 85%. After some googling, I found this was probably garbage collecting cycles. Sure enough, when I programmed System.gc() at p oints I knew there would be a lot of garbage, the stuttering was predictable but still obtrusive. A stutter of one second while drawing is not good at all. A stutter of one second while zooming in or out is tolerable. So with System.gc(), I can place my stutters.

I want to shorten my stutters. From what I've read, the best way to do that is to lessen the number of created objects that are discarded. In my main draw() loop I was creating a new rectangle object and discarding it 60 times a second. I guess the gc method has to fingerprint everyone of these objects no matter how small?

I made a global variable for that rectangle object and instead of creating a new object each time, I just changed its perimeters. The sped up gc() by about 50% I think.

But there is another portion of that loop that uses throw away PImages. For the most part, I only use PImages for the pixel information, except for the method "image(...). Is it possible to make these throw away PImages globals that don't go away but just change size and pixel information? I think that would really help my garbage collection stutters.

At this point I'm thinking of global indices. If gc() has to even fingerprint throw away variables, that could be a performance problem.

Any thoughts on this or suggestions for optimizing garbage collection in Processing would be greatly appreciated.

Tagged:

Answers

  • edited October 2017

    Is it possible to make these throw away PImages globals that don't go away but just change size and pixel information?

    • Yes it is, as long as they don't change their dimensions!
    • If you don't have many images w/ diff. dimensions, you can pre-create them.
    • Then you can use arrayCopy() from the source PImage::pixels[] to the dimensional corresponding working PImage::pixels[].
  • edited October 2017

    But they do change dimensions with the size of the brush and the distance from mouse and pmouse. I was hoping I could just set them at the mximum possible size and just change the pixel information and the width and height fields and the method "image()" would still work. Memory is not my problem. Garbage collection is. These objects are in the draw loop so they happen 60 times a second. They are small ( little cursor blits) but thats 60 objects a second. Otherwise, I'm going to have to go into how "image()" works ( I've glanced at it in the source with all the get native stuff) and make my own "image()" method.

  • edited October 2017

    Let me try to explain further. These are large images, so just pasting the entire image onto the screen is a performance hit. That has to be done as little as possible and when no actual user drawing is going on. The only need to post the entire image is when it has been zoomed in or out or has been dragged. In both cases, stuttering is tolerable but it should be as less as possible ( i.e., the gc should only be cleaning up things associated with that zoom or drag) . But small sections have to change when there is mouse movement or drawing/painting. They are relatively very small objects, but they accumulate rapidly at 60 per second. Basically they are little deltas created and discarded as PImages. But the dimensions change. I can easily guess the max and min they might be, but the actual dimensions will change every frame.

    I'm trying to think of a way these don't have to be new objects.

    It would be great if with PImage I could just read in a different number of pixels and change the width and height to match that array. That way, I could start the PImage at the maximum possible size and not have to create and discard a new object 60 times a second ( talk about litter!!).

    Also with all the (for int i = 0, i<b;i++) does the gc have to fingerprint all those disposable variables? I'm thinking of how Windows deletes files by putting a little tilde in front of them. No matter how big or small the file is, it takes time to put that tilde there. I'm thinking about using permanent global indices.

    Thanks for the reply. There's got to be a way to do this and I think I'm going to learn a lot more about java in the process. I wish I could think of a simple program to illustrate my problem but it is fairly complex to calculate the portion of an off screen image that must be blitted to the screen according to how the screen is zoomed or dragged.

  • Also with all the (for int i = 0, i<b;i++) does the gc have to fingerprint all those disposable variables?

    • Local variables & function parameters are created in the stack memory region.
    • Once a function returns, its stack is released w/o any GC involvement.
    • Sometimes, Java can instantiate objects in the stack instead of in the heap region, if it happens to find out they can't escape the stack.
    • In this case, the object is immediately removed along w/ local variables & parameters. No GC involvement either! \m/
  • "Once a function returns, its stack is released w/o any GC involvement." That's good to know! I don't have to worry about the indices :)

    It also suggests the idea of making these little PImages, stack objects? Disposed of without gc involvement?

  • Answer ✓

    It also suggests the idea of making these little PImages, stack objects?

    When we pass a PImage to function image(), the PGraphics canvas caches a weak reference copy of it.

    Therefore, the PImage escapes the function it was created; and thus can't be created in the stack region! :(

  • Thanks of the information and links. I've cleaned up a lot of the throw away objects in my program, but what was causing the major stutters was not just garbage cleanup. It was from using a large (4000x6000x3) multi dimensional array. Changing that to 3 one dimensional arrays drastically improved startup time and eliminated the stuttering. I'm going to ask about that in another thread. Thanks!

Sign In or Register to comment.