bytedeco / javacv

Java interface to OpenCV, FFmpeg, and more
Other
7.39k stars 1.56k forks source link

Doubts about usage of PointerScope #2223

Closed alessandrorimoldi closed 2 months ago

alessandrorimoldi commented 2 months ago

Hi, in these days I was facing a lot of memory problems that I resolved calling .deallocate on every instance of Mat I had in my code right after his usage. Searching around here and on google I found out that I can use PointerScope with try-with-resource instead of manually call deallocate all the time, but I have few questions:

Thank you

alessandrorimoldi commented 2 months ago

I explored the code by myself creating a simpler situation to analyse and yes, it's possible to use Using feature from Scala and obtain the desired behaviour by the code. It's something like:

def compareHistograms(reference: ImageData, candidate: ImageData): Double = {
  val result = Using(new PointerScope()) { pointerScope =>
    val referenceRgbMat = reference.getRgbMat
    val candidateRgbMat = candidate.getRgbMat

    val referenceRgbHistogram = HistogramUtils.getHistogram(referenceRgbMat, 8)
    val candidateRgbHistogram = HistogramUtils.getHistogram(candidateRgbMat, 8)

    compareHist(referenceRgbHistogram, candidateRgbHistogram, HISTCMP_CORREL)
    }
    result.get
}

And this code is the equivalent of:

def compareHistograms(reference: ImageData, candidate: ImageData): Double = {
  val pointerScope = new PointerScope()
  val referenceRgbMat = reference.getRgbMat
  val candidateRgbMat = candidate.getRgbMat

  val referenceRgbHistogram = HistogramUtils.getHistogram(referenceRgbMat, 8)
  val candidateRgbHistogram = HistogramUtils.getHistogram(candidateRgbMat, 8)

  val result = compareHist(referenceRgbHistogram, candidateRgbHistogram, HISTCMP_CORREL)
  pointerScope.close()
  result  

And ofc it doesn't make sense to have a static PointerScope as I was asking on the second bullet point of my original question. I'm justing wondering now which is the difference between calling .close or .deallocate on pointerScope instance. I've seen the implementation but I just don't get the difference between .releaseReference and .deallocate called on stacked pointers. What if I just call first pointerScope.deallocate and then pointerScope.close?

Thank you!

saudet commented 2 months ago

We can do whatever we need with PointerScope. You can think of each instance as a group of objects that should be deallocated together. Sounds good?

alessandrorimoldi commented 2 months ago

Yea, I was just wondering about the correct usage of it

saudet commented 2 months ago

Correct usage, well it's meant to emulate C++'s RAII, so is there something we can do with RAII that you can't seem to figure out how to do with PointerScope?

saudet commented 2 months ago

I'm justing wondering now which is the difference between calling .close or .deallocate on pointerScope instance. I've seen the implementation but I just don't get the difference between .releaseReference and .deallocate called on stacked pointers. What if I just call first pointerScope.deallocate and then pointerScope.close?

We need to have a close() method to implement the Closeable interface, it just calls dellocate().

You don't need to worry about Pointer.releaseReference(), that's used by PointerScope.

alessandrorimoldi commented 2 months ago

We need to have a close() method to implement the Closeable interface, it just calls dellocate().

I know that to use AutoCloseable interface you need to implement the close() method but the implementation of close() and deallocate() is not the same in PointerScope class, that's why I was wondering about the correct usage of this feature.

Anyway I have got your point and after few experiments with code I have cleared my doubts.

Thank you

saudet commented 2 months ago

I know that to use AutoCloseable interface you need to implement the close() method but the implementation of close() and deallocate() is not the same in PointerScope class, that's why I was wondering about the correct usage of this feature.

I see, right, close() doesn't directly call deallocate(). The latter is used to force deallocation, regardless of the status of the counter, because close() doesn't always call deallocate().