libgdx / gdx-liftoff

A modern setup tool for libGDX Gradle projects
Apache License 2.0
530 stars 50 forks source link

High CPU load #29

Closed JojoIce closed 4 years ago

JojoIce commented 4 years ago

Just letting liftoff sitting idle (maybe at a certain page) made the fan rev up to max and CPU load was quite high. Not a big deal, but also maybe just something that is easily fixed and nobody noticed yet.

tommyettinger commented 4 years ago

Might be vsync-related, I'll take a look. What OS/version are you running? I know people have reported issues with LWJGL3 apps (like liftoff) and very high framerate/CPU-usage/fan-speed on some kinds of Linux. It's also supposed to be fixed with the latest snapshots, so I'll see if those work here.

tommyettinger commented 4 years ago

Well, here's another beta build; this has the same fixes as in the iOS beta as well as limiting FPS to 30, which should be much easier on the CPU while staying responsive. Here's the jar in a zip: cpu-gdx-liftoff-1.9.11.3-SNAPSHOT.jar.zip

tommyettinger commented 4 years ago

I didn't mean to close the issue; I would like to know if this beta fixes the problem.

JojoIce commented 4 years ago

The snapshot crashed:

java -jar gdx-liftoff-1.9.11.3-SNAPSHOT.jar 
java(32424,0x70000bc64000) malloc: *** error for object 0x7fe880103000: pointer being freed was not allocated
java(32424,0x70000bc64000) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6

Tried with different JDKs and all crashed in one way or another, but so bad that no stacktrace is returned.

Tested it on Win and that works fine with the snapshot.

I have also noticed that the same thing (or similar) happens if I simply run the main class from Eclipse in a project created by liftoff. if I use Gradle run, then it is fine. I think it was the same thing with the jar generated by gradle that it crashed badly.

I noticed that the settings for liftoff are preserved between the different executions. I guess that is the kotlin stuff. You didn't change anything in that which isn't backwards kompatible? Even so I guess it would not crash this violently.

I tried to add Kotlin support to my Eclipse, but something did not work right, so I could not run liftoff from your code. Is the only thing needed to rip out all the Kotlin, to hardcode the size of the window? After the botched Kotlin install, Gradle started acting up and refused to parse any gradle files as well. Huge pain that still isn't fully fixed so I am not too keen on trying adding Kotlin now.

I will look into the crash from the generated project. I only used LWJGL3 and not legacy, could be good to compare the two maybe. Possibly there will be another ticket for the coredump issues.

On the other hand, the 1.9.11.2 version always spits out a stacktrace at startup, but survives. It could be related, and the snapshot does not handle it as well:

java -jar gdx-liftoff-1.9.11.2.jar 
Application was not launched on first thread. Restarting with -XstartOnFirstThread. Add VM argument -XstartOnFirstThread to avoid this.
Exception in thread "main" java.lang.ExceptionInInitializerError
    at org.lwjgl.glfw.GLFW.glfwCreateWindow(GLFW.java:1842)
    at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createGlfwWindow(Lwjgl3Application.java:450)
    at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lwjgl3Application.java:394)
    at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lwjgl3Application.java:380)
    at com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.<init>(Lwjgl3Application.java:108)
    at com.github.czyzby.setup.MainKt.main(main.kt:25)
Caused by: java.lang.IllegalStateException: GLFW windows may only be created on the main thread and that thread must be the first thread in the process. Please run the JVM with -XstartOnFirstThread. For offscreen rendering, make sure another window toolkit (e.g. AWT or JavaFX) is initialized before GLFW.
    at org.lwjgl.glfw.EventLoop$OffScreen.<clinit>(EventLoop.java:39)
    ... 6 more

I had a quick investigation regarding the actual ticket as well. I could not replicate the exact behaviour as I reported, but it could consistently trigger the issue by either minimising the window or switching desktop in both ways so that liftoff isn't visible. So you were already thinking about that. I guess the code is throttled by the vsync and that is probably not happening when it is not rendering, so it goes flat out. When I first detected the issue, liftoff was visible, but I used an external monitor. Maybe that had something to do with it. I don't have that available to test right now. I guess you probably already fixed it but thought I'd let you in on the details.

tommyettinger commented 4 years ago

So the 1.9.11.2 stacktrace is expected on MacOS and it recovers. MacOS needs that -XstartOnFirstThread argument to run LWJGL3 apps/games, so if the JAR is run without it, liftoff anticipates an error, recovers if it finds that it needs the argument, and relaunches with that argument to the JVM. I'm guessing something changed in libGDX 1.9.12-SNAPSHOT that's causing the malloc abort with the beta, I'm guessing on MacOS only (don't know the version). I'll test Linux in a bit; I don't have a Mac. EDIT: Linux works fine with JDKs from 8 to 14, testing HotSpot and OpenJ9, so it isn't a Unix thing, I think this is Mac-specific. What OS and Version Of That OS are you using?

JojoIce commented 4 years ago

Ah yes, macOS Catalina v10.15.6 MacBook Pro

tommyettinger commented 4 years ago

Hmm. According to https://stackoverflow.com/questions/22329005/mac-terminal-pointer-being-freed-was-not-allocated-error-when-opening-termin , this can be related to /Library/Preferences/there-is-a-saved-liftoff-file-here, though I don't know what the file is called (it's partially decided by libGDX). Personally I'd delete any gdx-liftoff preferences from that folder; something may have gotten partially written but is currently an invalid file. I can only find relevant info for this Abort trap: 6 bug on slightly older MacOS versions, like Mavericks, but it's definitely isolated to MacOS.

As to removing Kotlin, lol, the whole app is Kotlin, though it copy/pastes some related dependencies that are in Java (9207 lines of Kotlin source, 52006 lines of Java somehow). Almost all of the changes I make are in Kotlin, even though isn't my first pick of a language (I based liftoff on czyzby's gdx-setup, which was written in Kotlin, and was pretty much always ahead of libGDX's gdx-setup in some way but stopped receiving updates). It's sometimes possible to auto-translate Kotlin to Java, I guess. I figured Eclipse support for Kotlin was lousy despite zealous Kotlin proponents saying it existed; almost everyone probably develops Kotlin (a language made by JetBrains) in IDEA or Android Studio (IDEs by JetBrains), other than occasional VS Code users.

JojoIce commented 4 years ago

Ah, OK, then I will not attempt to create any pull requests :).

I could not find anything looking like it was created by liftoff in that folder you mentioned.

What I did try was to att the -XstartOnFirstThread from command-line, and that did the trick. Somehow the catch and restart voodoo must have gotten broken in this very build. Once it started I could see that the CPU load at least do not go up when liftoff is not rendering, but still uses about 10% was 60 - 80% before. Still a bit high for just being in the background, but that seems fine. There are probably more interesting problems to solve.

tommyettinger commented 4 years ago

More interesting... maybe. I'd really like to figure this out a bit better. The catch and restart voodoo could very easily be broken, and only Macs would notice. I can also lower the framerate to, say, 16, which should be fine for a GUI app (it should be fast enough that there's no delay between the user typing and showing those keystrokes). In the beta I posted, the background FPS is still 60 (I hadn't changed it), and it can go even lower (maybe 8, if foreground is 16). I think I'll look around the catch/restart stuff and see what might be different in libGDX 1.9.12-SNAPSHOT, then post another beta if I find anything.

tommyettinger commented 4 years ago

OK, here's a very rough attempt at diagnosing the startup issue... Now if liftoff has to attempt a catch-and-restart, it doesn't keep throwing the error, and it also prints the OS name in case that's what's not being detected correctly. This also slows down the frame rate to 16 foreground, 8 background. Here's the zipped jar, cpu2-gdx-liftoff-1.9.11.3-SNAPSHOT.jar.zip; if it prints anything during startup (or has a bad crash again...), knowing what it is could be very helpful. Thanks!

crykn commented 4 years ago

I ran the second jar file on my macbook (Mac OS 10.15.6) and it doesn't print anything except the following error message:

# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fff2ccb9924, pid=63022, tid=3331
#
# JRE version: Java(TM) SE Runtime Environment (9.0+11) (build 9.0.4+11)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (9.0.4+11, mixed mode, tiered, compressed oops, g1 gc, bsd-amd64)
# Problematic frame:
# C  [HIToolbox+0x27924]  _ZNK22THIThemeTextInfoFinder10GetOptionsEv+0x8
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/xyz/Downloads/hs_err_pid63022.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Abort trap: 6

The error log file created contains, inter alia:

Click to show ``` Stack: [0x0000700004ebd000,0x0000700004fbd000], sp=0x0000700004fbaca0, free space=1015k Native frames: (J=compiled Java code, A=aot compiled Java code, j=interpreted, Vv=VM code, C=native code) C [HIToolbox+0x27924] _ZNK22THIThemeTextInfoFinder10GetOptionsEv+0x8 C [HIToolbox+0x2784e] _ZN15TCoreTextEngine12VerifyLayoutEP16THIThemeTextInfoff12LayoutIntent+0x34 C [HIToolbox+0x2775b] _ZN15TCoreTextEngine22GetThemeTextDimensionsEdP16THIThemeTextInfoPdS2_S2_+0x2b C [HIToolbox+0x26247] _ZN10DataEngine17GetTextDimensionsEPKvdP15HIThemeTextInfoPdS4_S4_+0x10f C [HIToolbox+0x26106] HIThemeGetTextDimensions+0xbc C [HIToolbox+0x25a51] _ZN13HIMenuBarView16MeasureMenuTitleEP8MenuDatahPfi+0x1ab C [HIToolbox+0x257de] _ZN13HIMenuBarView15MeasureAppMenusEv+0xe6 C [HIToolbox+0x25367] _ZN13HIMenuBarView15EnsureBarLayoutEv+0x1a3 C [HIToolbox+0x24c77] _ZN13HIMenuBarView8DrawOnceE6CGRectS0_bbP9CGContext+0x243 C [HIToolbox+0x2494e] _ZN13HIMenuBarView8DrawSelfEsPK9__HIShapeP9CGContext+0x23a C [HIToolbox+0x243b6] _ZN13HIMenuBarView24DrawWithoutCustomizationEsPK9__HIShapeP9CGContext+0x52 C [HIToolbox+0x2434e] _ZN13HIMenuBarView22DrawingDelegateHandlerEP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv+0x102 C [HIToolbox+0x88ff] _ZL23DispatchEventToHandlersP14EventTargetRecP14OpaqueEventRefP14HandlerCallRec+0x4e6 C [HIToolbox+0x7d8d] _ZL30SendEventToEventTargetInternalP14OpaqueEventRefP20OpaqueEventTargetRefP14HandlerCallRec+0x149 C [HIToolbox+0x7c3d] SendEventToEventTargetWithOptions+0x2d C [HIToolbox+0x23ecd] _ZN6HIView8SendDrawEsP13OpaqueGrafPtrPK9__HIShapeP9CGContext+0x145 C [HIToolbox+0x23967] _ZN6HIView23RecursiveDrawCompositedEPK9__HIShapeS2_jPS_P9CGContexthd+0x23f C [HIToolbox+0x23b61] _ZN6HIView23RecursiveDrawCompositedEPK9__HIShapeS2_jPS_P9CGContexthd+0x439 C [HIToolbox+0x23399] _ZN6HIView14DrawCompositedEsP13OpaqueGrafPtrPK9__HIShapejPS_P9CGContext+0x32f C [HIToolbox+0x2305b] _ZN6HIView6RenderEjP9CGContext+0x33 C [HIToolbox+0x22783] _ZN10WindowData20PrepareForVisibilityEv+0x99 C [HIToolbox+0x789c8] _ShowHideWindows+0x11e C [HIToolbox+0x221b4] ShowHide+0x23 C [HIToolbox+0x12217] _ZN9MBWindows18GetWindowOnDisplayEjh+0x127 C [HIToolbox+0x11ff7] _ZN15MenuBarInstance15ForEachWindowDoEhU13block_pointerFbP15OpaqueWindowPtrjE+0xb7 C [HIToolbox+0x11efb] _ZN15MenuBarInstance28SetBoundsAndUpdateResolutionEv+0x67 C [HIToolbox+0x11a72] _ZN15MenuBarInstance4ShowE21MenuBarAnimationStylehhhh+0x118 C [HIToolbox+0x114aa] _ZN15MenuBarInstance21UpdateAggregateUIModeE21MenuBarAnimationStylehhh+0x324 C [HIToolbox+0x110aa] _ZN15MenuBarInstance16ForEachMenuBarDoEU13block_pointerFvPS_E+0x2e C [HIToolbox+0x11042] _ZL25UpdateAllAggregateUIModes21MenuBarAnimationStyleh+0x7e C [HIToolbox+0x10fae] SetSystemUIMode+0xa5 C [AppKit+0x319fb] -[NSApplication finishLaunching]+0x2dc C [AppKit+0x313f0] -[NSApplication run]+0xf4 C [libglfw.dylib+0x10a85] C [libglfw.dylib+0xa416] j org.lwjgl.system.JNI.invokePPPP(IIJJJJ)J+0 j org.lwjgl.glfw.GLFW.nglfwCreateWindow(IIJJJ)J+14 j org.lwjgl.glfw.GLFW.glfwCreateWindow(IILjava/lang/CharSequence;JJ)J+37 j com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createGlfwWindow(Lcom/badlogic/gdx/backends/lwjgl3/Lwjgl3ApplicationConfiguration;J)J+284 j com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lcom/badlogic/gdx/backends/lwjgl3/Lwjgl3Window;Lcom/badlogic/gdx/backends/lwjgl3/Lwjgl3ApplicationConfiguration;J)V+2 j com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.createWindow(Lcom/badlogic/gdx/backends/lwjgl3/Lwjgl3ApplicationConfiguration;Lcom/badlogic/gdx/ApplicationListener;J)Lcom/badlogic/gdx/backends/lwjgl3/Lwjgl3Window;+23 j com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application.(Lcom/badlogic/gdx/ApplicationListener;Lcom/badlogic/gdx/backends/lwjgl3/Lwjgl3ApplicationConfiguration;)V+233 j com.github.czyzby.setup.MainKt.main([Ljava/lang/String;)V+288 v ~StubRoutines::call_stub V [libjvm.dylib+0x3a33ed] V [libjvm.dylib+0x3dc859] V [libjvm.dylib+0x3df207] C [java+0x4dfa] JavaMain+0xb8d C [libsystem_pthread.dylib+0x6109] _pthread_start+0x94 C [libsystem_pthread.dylib+0x1b8b] thread_start+0xf C 0x0000000000000000 ```
tommyettinger commented 4 years ago

Hmm. Can anyone on MacOS 10.15.x run any LWJGL3 apps right now? There's some question about it in LWJGL3's repo https://github.com/LWJGL/lwjgl3/issues/538 . Since I don't have a Mac now, I can't test easily, and this particular issue is barely documented anyway... I'm really not sure how the latest LWJGL3 changes affect -XstartOnFirstThread, but it seems like they do somehow. @crykn , it's very odd that nothing printed at all; I wrote in some debug printing before it's supposed to start a new window. Can you run with java -XstartOnFirstThread -jar gdx-liftoff-1.9.11.3-SNAPSHOT.jar and see if that at least works? Or prints anything?

payne911 commented 4 years ago

I tried to add Kotlin support to my Eclipse, but something did not work right, so I could not run liftoff from your code. Is the only thing needed to rip out all the Kotlin, to hardcode the size of the window? After the botched Kotlin install, Gradle started acting up and refused to parse any gradle files as well. Huge pain that still isn't fully fixed so I am not too keen on trying adding Kotlin now.

As to removing Kotlin, lol, the whole app is Kotlin

@JojoIce I'm currently working on changing that!

-> https://github.com/payne911/gdx-setup-generator

Still a WIP, though.

crykn commented 4 years ago

@tommyettinger When using the -XstartOnFirstThread arg the jar file can be executed and works as expected. I tested it with some another LWJGL3 application and the same issue is happening there as well.

The problem seems to be that liftoff is trying to catch an exception if the -XstartOnFirstThread arg is not present, but in later LWJGL3 versions (the culprit being https://github.com/glfw/glfw/commit/ea7eb2ddab823e21c846c68d112d90f91fcba318) the whole JVM crashes, so this doesn't work anymore. I tested programatically restarting the JVM if it doesn't have the -XstartOnFirstThread arg (using my implementation here) and that does work.

@JojoIce FWIW I also couldn't get liftoff running in Eclipse and had to switch to IntelliJ.

tommyettinger commented 4 years ago

OK, I'm using @crykn 's StartOnFirstThreadHelper workaround now; I don't know if I did things correctly, but here goes: mac-gdx-liftoff-1.9.11.3-SNAPSHOT.jar.zip . Thanks for being patient with me here! This whole set of incompatibilities is so strange...

crykn commented 4 years ago

This jar file works!

JojoIce commented 4 years ago

Yup, i basically see the same as @crykn. Only difference is the crash looked a bit different, probably depending on what java version is running: java -jar gdx-liftoff-1.9.11.3-SNAPSHOT.jar 2020-09-24 14:20:10.015 java[86513:5849822] *** Assertion failure in +[NSUndoManager _endTopLevelGroupings], /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/Foundation/Foundation-1677.104/Foundation/Misc.subproj/NSUndoManager.m:363 2020-09-24 14:20:10.018 java[86513:5849822] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+[NSUndoManager(NSInternal) _endTopLevelGroupings] is only safe to invoke on the main thread.' *** First throw call stack: ( 0 CoreFoundation 0x00007fff3924cb57 __exceptionPreprocess + 250 1 libobjc.A.dylib 0x00007fff720935bf objc_exception_throw + 48 2 CoreFoundation 0x00007fff39275d08 +[NSException raise:format:arguments:] + 88 3 Foundation 0x00007fff3b967e9d -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191 4 Foundation 0x00007fff3b8a45ee +[NSUndoManager(NSPrivate) _endTopLevelGroupings] + 440 5 AppKit 0x00007fff3643165c -[NSApplication run] + 864 6 libglfw.dylib 0x0000000119a80a85 libglfw.dylib + 68229 7 libglfw.dylib 0x0000000119a7a416 libglfw.dylib + 42006 8 ??? 0x000000011b281407 0x0 + 4750578695 9 ??? 0x000000011b270b10 0x0 + 4750510864 10 ??? 0x000000011b270b10 0x0 + 4750510864 11 ??? 0x000000011b270b10 0x0 + 4750510864 12 ??? 0x000000011b270b10 0x0 + 4750510864 ) libc++abi.dylib: terminating with uncaught exception of type NSException Abort trap: 6

Other than that, the app is now hovering around 5% CPU, rendering or not, so that seems perfectly fine.

@payne911 That looks very interesting indeed. Will follow that.

Regarding the voodoo needed to make it "double-clickable" (no runtime params on macOS), do one need to add a kotlin wrapper around it or is it possible to implement that in pure java? Just thinking that it would be really nice to be able to spread the game jar in the same way as liftoff.

High CPU load is fixed in latest jar, so OK to close ticket.

tommyettinger commented 4 years ago

OK, I'll close. I think the easiest way to make a jar have no runtime params on MacOS is probably to use @crykn 's Guacamole library, which I'm about to add to liftoff's third-party extensions.

Also that crash looks incredibly weird; I hope it isn't still happening?