BiglySoftware / BiglyBT

Feature-filled Bittorrent client based on the Azureus open source project
https://www.biglybt.com
GNU General Public License v2.0
1.59k stars 155 forks source link

[Suggestion] Packaging and GC settings #3372

Open UtilFunction opened 2 months ago

UtilFunction commented 2 months ago

The current packaging of BiglyBT is rather heavy and impractical. Jlink and jpackage have been around for quite a while and would improve deployment of BiglyBT. Jlink allows us to generate a modularised and stripped down JRE for our application, which can then be packaged into installers and portable executables using jpackage.

I would also suggest enabling ZGC -XX:+UseZGC and -XX:+ZGenerational for low GC pauses and immediate release of memory to the OS.

Ghost-chu commented 2 months ago

I don't believe BiglyBT is a good candidate for ZGC, despite the many benefits of ZGC - low latency, high performance. But these are not metrics that are critical to BiglyBT, which is not an enterprise application for which a few milliseconds of GC pause can be critical. BiglyBT is not an enterprise application, for which a few milliseconds of GC pauses may be critical. BiglyBT is clearly not suitable for this -- especially if BiglyBT still needs to support Java8, which ZGC does not.

However, if BiglyBT switches to G1GC, it may be able to benefit from -XX:+UseStringDeduplication (to reduce BiglyBT's required heap size by compressing the same strings in memory). And if switching to a higher version of Java, you may also benefit from -XX:+ShrinkHeapInSteps (to return freed heap memory to the system immediately). From the user's point of view, this will reduce memory consumption very significantly.

If upgrading to Java 21, you can also use Virutal Thread to reduce resource overhead.


These are the things that BiglyBT probably really needs, and replacing the GC would not be a significant experience improvement. But you have to admit that even though BiglyBT doesn't use them, it works well enough so far.


jlink and jpackage can be considered -- If your application is built from the ground up with these in mind. However for BiglyBT, which has been in development for a considerable amount of time, the cost of time behind the scenes is quite scary. All the code had to be modularized, and the amount of work behind that would be difficult for even a large enterprise to accept.

UtilFunction commented 2 months ago

Actually, the biggest reason to switch to ZGC would be the fact that, unlike other GCs (with the exception of Shenandoah), ZGC immediately returns memory to the OS. One of the reasons people are reluctant to use desktop Java applications is because they are afraid of how much memory the JVM reserves. This problem does not exist with ZGC. As for GC pauses, As for GC pauses, I think any GUI application benefits from GC pauses that are as short as possible. Bitwig Studio has been using them in production for some time now.

Applications do not have to be modular in order to benefit from jlink. All that needs to be done is figure out which modules are being used by using jdeps. There's also a gradle plugin that does this automatically for non-modular applications but obviously Maven is being used for BiglyBT.

ferdnyc commented 1 month ago

As for GC pauses, I think any GUI application benefits from GC pauses that are as short as possible.

Have you ever noticed a detectable GC pause in BiglyBT? Because, I haven't.

Yes, returning memory to the system faster could potentially be a boon, but worrying about GC pauses feels like a solution looking for a problem.

ferdnyc commented 1 month ago

Applications do not have to be modular in order to benefit from jlink. All that needs to be done is figure out which modules are being used by using jdeps.

I know fairly little about jlink, but it sounds like BiglyBT's plugin system would be an issue with that, wouldn't it?

There are plenty of plugins that use modules not required by the base application. Wouldn't a jlinked runtime need to be configured for all possible plugins? (Which is not possible, because BiglyBT also explicitly supports third-party plugins. So, there is no way to define the universe of all possible modules that might be required in a given instance of the application. If I'm understanding correctly.)

ferdnyc commented 1 month ago

So, there is no way to define the universe of all possible modules that might be required in a given instance of the application.

(Well, not any smaller than, "all of them", I mean.)

ferdnyc commented 1 month ago

Oh, and...

One of the reasons people are reluctant to use desktop Java applications is because they are afraid of how much memory the JVM reserves.

[citation needed]

BiglyBT's memory overhead pales in comparison to its memory requirements from Actual Data™ loaded into the application; torrenting involves moving a metric fuckton1 of data around, after all. The notion that the application's memory consumption is accidentally wasteful, or can be significantly reduced with more efficient management, is — I fear — largely wishful thinking.

I'd be happy to be proven wrong, but I'm not expecting to be.

Notes

  1. (It's the SI unit for encoded media streams.)
UtilFunction commented 1 month ago

Have you ever noticed a detectable GC pause in BiglyBT? Because, I haven't.

I think I have but it's something I should have to measure objectively.

There are plenty of plugins that use modules not required by the base application. Wouldn't a jlinked runtime need to be configured for all possible plugins?

Yes but even with all plugins I think there's still quite a lot that can be stripped away from the JDK. It's something I could figure out, that's what jdeps is for. It's just that BiglyBT seems to be a bit tricky to build/run from source - or at least it is for me because I'm used to the typical Maven/Gradle build.

I'll give it a shot and report back.

UtilFunction commented 1 month ago

I made it work.

  1. I figured out which modules are needed by launching jdeps -cp .\* -recursive -s .\BiglyBT.jar which yielded:
    BiglyBT.jar -> JDK removed internal API
    BiglyBT.jar -> .\commons-cli.jar
    BiglyBT.jar -> java.base
    BiglyBT.jar -> java.desktop
    BiglyBT.jar -> java.management
    BiglyBT.jar -> java.naming
    BiglyBT.jar -> java.xml
    BiglyBT.jar -> .\swt.jar
    commons-cli.jar -> java.base
    swt.jar -> java.base
    swt.jar -> java.desktop
  2. Generate a stripped down JRE with jlink --add-modules java.base,java.desktop,java.management,java.naming,java.xml --strip-debug --no-man-pages --no-header-files --compress 0 --output ./jre
  3. Generate a package with jpackage.exe --type app-image --app-image .\jre --input .\input\ --main-jar .\BiglyBT.jar The inpult folder needs to include all jars and folders/files that are required for the application. The zipped application image or the .msi file sizes ~42mb which is pretty good considering it includes the JRE required to run the application.

Obviously more parameters for the app-version, icons, file associations etc. would have to be specified in the jpackage command. The parameters can be found here. Hope this helps.

ferdnyc commented 1 month ago

figured out which modules are needed by launching jdeps -cp .* -recursive -s .\BiglyBT.jar

... Right, but that's with no plugins, then, right? That's the thing I'm not understanding here. Is this a version of BiglyBT where you can still visit https://plugins.biglybt.com/, download anything off that list, and have it work normally without hitting problems due to missing classes in the runtime?

UtilFunction commented 1 month ago

Yes I am able to install the plugins.

Ghost-chu commented 1 month ago

I also use Kotlin in my own plugins, and I don't think that will work.