brianhsu / Live2DForScala

Live2D Avatar Studio for Scala (JVM / Linux / Windows / MacOS)
MIT License
23 stars 3 forks source link

fix swt version a possible cause of stucke #9

Closed jjiill888 closed 1 month ago

jjiill888 commented 1 month ago

The swt version may have a memory leak now.

I'm trying to find out why memory usage reaches 600mb for a while (normal usage is 350m on my computer,)

brianhsu commented 1 month ago

Thank you, but this PR does not make sense to me.

The code listed in this PR won't fix any memory leak issue. Because what you did here is just call display.dispose even when the are exceptions thrown out during line 23 - 34.

But:

  1. If line 23 - 34 doesn't throw any exception, and the program terminate normally (for example, click on the close button), then display.dispose would be called as expected.
  2. If any exception is thrown, we could not assume that display is in correct state, and calling dispose might cause other issue, and we also shouldn't report to OS that this program is terminated normally (using System.exit(0)). That's why I just left it and let JVM terminate. No exception should propagate to this UI loop, if so, something serious happens and we just terminate JVM, all resource taken by JVM should be released then.

You also might add the following code to verify that this try block does nothing to this memory issue. You will notice the memory increase pattern remain the same regardless if we have try-catch or not.

  def main(args: Array[String]): Unit = {
    setupUILayout()
    setupAvatarEventListener()
    setupMemoryMonitor()
    ....
  }

  private def setupMemoryMonitor(): Unit = {
    val executor = Executors.newSingleThreadScheduledExecutor()
    executor.scheduleAtFixedRate(() => {
      val total = Runtime.getRuntime.totalMemory()
      val free = Runtime.getRuntime.freeMemory()
      val usageInMB = (total - free) / 1024 / 1024
      println(s"Memory Usage: $usageInMB MB")
    }, 0, 1, TimeUnit.SECONDS)
  }

There are other reasons cause this issue. I've done some simple tests, found it might related to the SWT Combox rendering. When the string in the Combox exceed the visible area, it starts to eat up memory quickly. But I need more time to verify this, and see is it a SWT underlaying bug or I've done something wrong in my code.

If you are interested, you could do the following to verify this behaviour:

  1. Add the memory monitoring output as above.
  2. Edit SWTWithLWJGLMain.scala with following change. Replace the avatar drawing area with a SWT button to isolate the problem.
    - private val avatarArea = new SWTAvatarDisplayArea(sashForm)
    + private val placeholder = new Button(sashForm, SWT.PUSH)
  3. Also comment out the body of setupAvatarEventListener() to make the code compilable.

Run the program, and adjust the width of left panel. From what I observed, when the size of panel is too small and the are combox only display partial content of current selection (for example, the sound device list), the memory usage will rapidly increase (about 1 ~ 2 MB per 4 ~ 5 seconds on my host).

And adjust the left panel so that every combox could display without being truncated, the memory usage is pretty consistent now.

So I don't think this PR will solve this issue, sorry.

jjiill888 commented 1 month ago

Thank you for the explanation you gave, I should have thought about it more