How do i lower or remove the amount of lag spikes within my game app

Hello App Inventors, I have been recently working on a project of mine for a computer science class and I was having an issue with the amount of lag. Here is the code:

More Info:
The app/game consists of a joystick, a player sprite, and multiple rock projectile sprites. The player is a surfer and uses the joystick to dodge oncoming rocks. The code works as intended, but after playing for about 30 to 40 seconds a noticeable lag spike occurs. It reoccurs about every 5 seconds after that. I understand that I am doing a lot of rendering and computing a lot of information within a short period of time(45ms) for App Inventor, but I am interested in why such a noticeable lag spike happens so late within the app and why it is not a constant drop in framerate as shown in other games or apps.

I am happy to answer any other questions if it will help in any way.
Thanks for reading and helping with my project!

Welcome Tyler.

  • you are aware App Inventor is NOT a game engine. AI's graphics are slow compared to Java compilers (which make the fast action Android games which are multi threaded; AI is not.
    )
  • I suspect this behavior is a memory issue. You said you do a lot of rendering and calculation; yes that could cause a lag after system memory fills up.
  • 45 ms ? That is awfully fast. An eyeblink is about 300 ms. Do you get the same noticeable lag if you increase to 100 or 200 ms? Slowing down might not affect your game enjoyment. :wink:
1 Like

Thanks for the quick response :slight_smile:. I took your word and changed the rendering time from 45ms to 200ms. Unfortunately, The same spike still happens around the same time. While less noticeable as the spikes blend more to the lower framerate, It is still noticeable and I also attempted to move the time from 200ms to 300ms and it is still relatively visible. Anything over 300ms per frame is something close to unusable.

I do understand the capability of MIT App Inventor, but I am curious to ask if it will ever be improved in performance. While I understand that App Inventor is "NOT" a game engine, It would be nice to see advancements that could possibly allow for this category(obviously to an extent).

Why this happens:

This is how App Inventor Blocks work:
Understanding an App's Architecture

Also see The model of asynchronous processing in AI2 by Franklyn_A_Turbak

and https://cs.wellesley.edu/~tinkerblocks/CCSCNE14-AI2-events-first-paper.pdf

Perhaps. Notice that currently AI is based on using a single processing thread.

@ewpatton what would it take to make AI multithreaded and to have faster graphics?

Thanks for the document! While I am not able to debug my app at the moment, based on Franklyn Turbak's information, it seems that running multiple higher-speed clocks at the same time is most likely the issue. Instead of using one clock to run as a heartbeat for the whole program, I use multiple(one for the movement of the joystick, one for the player's sprite and projectile positions, and another for the animation of the projectiles) and I think that the problem arises from a buildup of requests in the queue for the thread. Hopefully based on this information I can solve the issue later.
Thanks for the help!

1 Like

Game engines only moderately benefit from multithreading. The main reason being that all of the work still has to be accomplished by the next frame otherwise the framerate drops, and there is only so much work that can be done in parallel (running at 60 fps means doing all of that work in 16 ms or less). Most game engines will be written in C or C++ and then there is a JNI layer that calls through to the native code layer. In fact, the Android SDK has tutorials on how to use the native development kit (NDK) to write an app without ever really having to go through the Java layer. There's a secondary benefit in that much of the logic can sometimes be reused cross platform (cf. Unity).

The second major thing that game engines try to avoid is creating garbage that has to be collected. The spikes that you're observing are due to the virtual machine running the code needing to pause to clean up the results of intermediate computations. My guess is that on your device it takes about 30-40 seconds for the main memory available for the app to be exhausted and then the garbage collector (GC) runs. This frees up some memory enough until a few seconds later at which point the freed memory has been exhausted again and the GC runs. Rinse and repeat. The likely culprit for this is in the ChangeFrame function where you are toggling between two different images every other frame. App Inventor does not cache images, so the causes the image to be read from the assets every time, scaled, etc. and then drawn. The previous image will hang around in memory until the GC runs to clean it up, resulting in the spikes while the world is paused for the GC operation. Some devices use parallel GC so that this is not needed but the actual functionality will depend on the Android version, etc.

One optimization you could do, although it is a bit of work,* would be to double the number of image sprites. This probably sounds counterintuitive, but the way it would work is that you would have 2 image sprites per entity, one with the rock_anim1.png image and the other with rock_anim2.png. Then, rather than swapping the images in/out you toggle the visibility of the two image sprites. This way, the amount of memory stays fairly constant once all of the image sprites have been initialized and won't require triggering the GC as frequently.

We use a similar technique in the PICaboo tutorial when swapping images of the crying/happy babies. By having the images already preloaded in memory it is much faster to change the visibility of the images between frames rather than reload the images on every frame.

* Technically all optimizations are work so it might go without saying...

1 Like

Because the use of animated frames was not extremely essential to my app I decided to just remove it altogether. This did bring the amount of freeze time for the spike down, but there is still a noticeable spike that lasts about 1 second. Perhaps, are there any other variables or objects that are considered "garbage" that would need to be thrown away?

--On a second note.
I'm not entirely sure about the difference in App Inventors capabilities between IOS and Android, but to give further information, I am running my app using IOS on an iPhone 14.