[SOLVED] Memory leak using Canvas context2d.getImageData



  • Consider the following minimal example (not very useful, but it serves to expose the problem):

    Timer {
        interval: 500; running: true; repeat: true
        onTriggered: canvas.requestPaint()
    }
    
    Canvas {
        id: canvas
        property var imageData
        
        onPaint: {
            var ctx = canvas.getContext("2d");
            if (canvas.imageData) {
                 // if we have image data from a previous paint, draw it translated 10px up.
                 ctx.drawImage(canvas.imageData, 0, -10);
            }
    
            // draw something on ctx
    
            // save the image data of the ctx on canvas.imageData, for using that in the following paint
            canvas.imageData = ctx.getImageData(0, 0, canvas.width, canvas.height) // this causes a memory leak
        }
    }
    

    A Timer force a Canvas paint every 500ms. In every paint (except the first) I want to redraw the previous image of the canvas, translated by 10px up, then draw something on the canvas, and then save the image for the next paint.

    The code works as expected, but I have a memory leak when calling ctx.getImageData.
    I assumed that replacing canvas.imageData with a new call to ctx.getImageData would have garbage collected the old canvas.imageData, but this is not the case.

    I tried adding

    delete canvas.imageData.data
    delete canvas.imageData
    

    After drawing the image in every paint cycle, I have no errors, but it doesn't solve the memleak.

    What I'm doing wrong here? Is there a workaround?

    Thank you very much for your help!



  • Solved thank to the help of inz on IRC.

    I've added the line

    gc()
    

    just after the line

    canvas.imageData = ctx.getImageData(0, 0, canvas.width, canvas.height) // this causes a memory leak
    

    And the memleak disappeared. Seems like the automatic garbage collector didn't run often enough for my use case, so the call to gc() is necessary to force the garbage collection.


Log in to reply