Android cold app start: How to optimise time to Application.onCreate? - android

My current app takes for a cold start ~8 seconds and I want to optimize that.
For that reason I added a log entry in my Application onCreate (Application, not Activity)
override fun onCreate() {
Log.d("myTag", "Calling Application onCreate()")
....
}
When looking in the logs and measuring the time, I found out that the above mentioned 8 seconds consist of the following:
Tapping app icon => Application.onCreate = 4 seconds
Application.onCreate => my Activity visible = 4 seconds
I know I can optimize the time from Application.onCreate() onward. It's my code and I can speed this part up.
But how can I optimize the time the system needs until my Application.onCreate is called?
Thanks!

Sounds like a great usecase for systrace. I usually use (at least) the gfx, input, view, wm, am, res, dalvik, bionic, and sched categories. A -b 10000 to ensure a sufficient buffer size doesn't hurt.
You'll get an html file which can be loaded in a browser, or opened through Chrome/Chromium's built-in chrome://tracing page.
At the top, you'll see CPU details like usage% and which thread is running at which time. Then, you'll see all the processes on the device, containing nested colored blocks ("segments") with information about what's currently going on. At the top of each thread, there is a small colored bar: white is "sleeping" (this includes waiting on a mutex), blue is "waiting for CPU", green is "running on CPU".
If there is a segment that seems interesting but you don't understand the exact meaning of, a search for the text at https://cs.android.com/ can be useful.
In any case, my guess is that you either have some library linking or ContentProviders that take time before Application.onCreate. Both of those would be visible in a systrace. And if my guess is wrong, you'll likely find something else. Good luck! :)
(it could also be class initialization... it'll be interesting to hear what you find!)

Related

Kotlin: Why Array and ArrayList are not emptied before a rerun?

My scientific app is fully dynamic and there is only one activity, no fragment or intent.
In some situations, I need to finish the app completely.
So I run
(this as Activity).finishAndRemoveTask()
It works smoothly since Lollipop (Android 5.0), version 21.
Apparently, no app traces or services remains in the memory.
However, I've found a huge problem.
I have some global array or array list (I didn't see other variables).
that remains intact with a new rerun, even a I have a declaration
that empties that variables. It doesn't happen with a rerun via debugger,
should be a new rerun from cell phone.
Below I show a schematic example. I declare in one .kt file, outside any class or function.
class DispFu(
var id: Int = 0,
var isKeyl:Boolean=false,
}
var vDispFu = arrayListOf<DispFu>()
After, I populate vDispFu inside onCreate processing and reach 134 items.
To prove it, I've recorded a file on my phone inside my activity onCreate processing, before exit the program.
fun now():String{
var hora = LocalTime.now()
return "${hora.hour}:${hora.minute}:${hora.second}"
}
var fileDep:File = createOrGetFile(Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_DOWNLOADS),"DepCalc","") // File for debugging
fileDep.appendText("${now()} -> vDispFu size is ${vDispFu.size}\n")
Below there are 2 runs: the first run (inside debugger) and a independent rerun. Here is the file content:
11:3:2 -> vDispFu size is 0
11:3:18 -> vDispFu size is 134
I know that global variables are not recommended, but I just wanted to understand what is going on. It doesn't make sense to me.
If someone could give me some clue about what is happening and give me some alternative strategy, it would be great!
Obviously, for practical reasons, the solution could not involve completely reformulating the program, which has almost 40 thousand lines...
Finishing an Activity doesn't shut down your entire Application or VM, so all global variables continue to stay in memory. When you rerun your application with the debugger, it actually restarts the VM, which is why you're seeing it get cleared in that case.
System.exit() is not an ideal solution since it restarts your VM process. There will be extra churn to do that. It's really intended for abnormal unrecoverable errors. Not necessarily a problem in your particular case.
The more proper way to handle this would be to put your top-level data in a singleton and clear it manually when you are finishing the Activity.
I've solved my problem:
Sometimes, it is incredible how the effort to externalize a problem sometimes helps to solve it ....
The below procedure to quit completely an app:
(this as Activity).finishAndRemoveTask()
It's not enough, despite all the posts about it on Stack Overflow that advocate this strategy.
It's necessary includes other command:
(this as Activity).finishAndRemoveTask()
System.exit(0)
Now:
11:26:25 -> vDispFu size is 0
11:27:1 -> vDispFu size is 0

How can I tell, in onDraw, whether or not I'm inside Android Studio?

I have a custom view that renders part of itself (pink area) in onDraw. It does this, via a class instance set via adapter/binding. I have no problem with the 117 and details controls at design time. However, this pink area is resulting in a call to onDraw within Android Studio.
Everything's ok at runtime. However, I am getting (and rightfully so) an Android Studio error message - because the class that I use to do the drawing hasn't been instantiated.
So, my question is:
Can I detect, in code, whether or not the app is running (rendering really) inside AS (as opposed to having been deployed to an emulator or device)?**
It might be something like if (BuildConfig.DEBUG), or perhaps something [entirely] different. (There's certainly nothing [else] in the BuildDebug instance that'll help.)
Ultimately, I see my current
override fun onDraw(canvas: Canvas) {
:
:
puzzle.doSomething
replaced with something like:
if (!INSIDE_ANDROID_STUDIO)
puzzle.doSomething
I spent over an hour searching online. With no luck. It's hard to ask "How do I know if I'm running in the Android Studio IDE?" and not get a bazillion links concerning:
Why isn't Android Studio running [correctly]
How to tell if another app is running
How to tell if your app is in the fore or background
Why this or that isn't rendering correctly
But nothing on point. I did numerous searches of "UninitializedPropertyAccessException" and "Render problem" as well.
You can do it by checking what returns the isInEditMode() method. If true your view is displayed in AS or other tool, otherwise - it`s on a device.
Indicates whether this View is currently in edit mode. A View is usually in edit mode when displayed within a developer tool. For instance, if this View is being drawn by a visual user interface builder, this method should return true.
https://developer.android.com/reference/android/view/View#isInEditMode()

Android Rubik's Cube Kociemba optimal solver memory shortage

I'd like to ask for some help about the following problem I have.
I'd like to create an application that solves the Rubik's cube with an optimal solution. I downloaded the following library, whitch supposedly does just that using the Kociemba's Algorithm.
http://kociemba.org/twophase.jar
Apparently it can solve the cube in under 0.5 sec, but in my app it never returned the solution due to memory problems. I know it works, I tested it with wrong inputs and it returns the documented error codes.
I call it in my onCreate method like this:
resultTxt = Search.solution(data, 21, 10, true);
resultTxt is a String variable and it should contain the solution.
It quickly eats up the memory.
I tried it with IntentService without success. By this I mean it didn't really changed anything.
As i didn't find any evidence of anyone using this library in any android application, I thought I would ask someone who is more experienced than me.
Is there any way I could make this work on Android, or is this as impossible as I thought?
It may be a bit late, but I was also facing this issue quite recently when I was working on a Rubik's-Cube-solving-robot using an Android-Smartphone for scanning the cube and computing the solution, so I'll put here what I have found out.
What is the problem?
Let's start off by discussing where the problem causing that performance issue actually is located.
The reason for that being so slow is the class CoordCube, which looks (very simplified) like this:
class CoordCube {
short[] pruneTables;
static {
/* compute and save ~50MB data in `pruneTables` */
}
}
Basically what it does, is to load a pretty big amount of data into lookup-tables which are required for a fast solving procedure. This loading is automatically executed by the JVM once this class is first instantiated. That happens on line 159 in Search.solution():
/* simplified code of solution() */
if (cube.isValid()) {
CoordCube c = new CoordCube(); // pruning tables will be loaded on this line
That is also the reason why this method executes in negligible time as long as the passed cube is invalid, since it never gets to load the tables.
Possible Solutions:
Now that we have identified where the problem is located, let's focus on how to solve it.
I have come up with 3 different approaches, where the first one is probably the easiest (but also the slowest execution wise ...) and is also used in my App. The other two are just ideas on how to improve the performance even more.
Approach 1:
The first and most simple approach is to just manually preload the lookup tables in a kind of LoadingActivity with a ProgressBar showing our current progress. For that we first want to be able to manually control exactly when which tables are loaded (when the class is first instantiated is not precise enough), like this:
loadTable1() {
/* load pruning table number 1 */
}
For that I have written some simple utility here (code is too long to paste). Make sure to check out my instructions there on how to properly import that code in your App.
Also we will probably want to do the loading in the background, namely in an AsyncTask. This is how I have done it in my application (PruneTableLoader is included in the previous link):
private class LoadPruningTablesTask extends AsyncTask<Void, Void, Void> {
private PruneTableLoader tableLoader = new PruneTableLoader();
#Override
protected Void doInBackground(Void... params) {
/* load all tables if they are not already in RAM */
while (!tableLoader.loadingFinished()) { // while tables are left to load
tableLoader.loadNext(); // load next pruning table
publishProgress(); // increment `ProgressBar` by one
}
return null;
}
#Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
/* increment `ProgressBar` by 1 */
}
}
When using my PruneTableLoader, the loading of all tables needs about 40s on my Samsung Galaxy S3 with 250 MB RAM free. (in contrast it needs well over 2min when loading them automatically and in addition often results in a crash ...)
That may still sound quite slow considering it needs < 1s on PC, but at least you must only do that once, since Android caches the static-variables and you so don't have to load them on every startup of your App.
Approach 2: (untested)
I assume it would be faster to save the pruning tables in a file or a database and load them from there instead of always recomputing them. I have not yet tested that though and it will probably require quite some work getting the saving and loading to work properly. (also maybe it's not even faster because of access times)
Approach 3: (untested)
Well, the hardest and also by decades most work expensive solution would be, to simply rewrite the whole algorithm in C or C++ and invoke it in the App via JNI. (Herbert Kociemba has not published his C-sourcecode yet as far as I know ...)
This is going to be the performance wise fastest solution for sure. (also for the solving procedure itself)
All in all approach 1 is probably the effort/benefit-wise best approach for the beginning (and also was for me), so I would recommend you to go with that, in case the loading time is not such a huge issue for your Application.
I'm not completely satisfied with the performance of that myself though, so I may try out approach 2 and maybe even approach 3 some time in the future. In case I do that, I will update this post with my results then.

AndEngine - setText on Text entity causing hiccups in first seconds

Imagine score counter made with Text() entity. Simple.
After I start a game, calling setText() causes launching a GC_EXPLICIT that slows down a game causing freezes, and after a few calls - problem disappears. Firstly I thought it's a problem with Strings and concatenation in Java, so I used a StringBuilder. The problem still exists. If I change setText("$" + score + "M") to simple setText("0") no hiccups are noticed!
The problem is in Font. Creation of Texture doesn't actually load characters to this Texture! All you need to do is after creating Font simply call:
pFont.prepareLetters("0123456789".toCharArray());
with all chars you need.
Occasional hiccups that were caused by GC_EXPLICIT were happening because Font in update() was explicitly calling System.gc(). Removing this line we were back on track below the green line, yeah! 60fps.
However, the author of AndEngine might had reasons for this explicit call. Since the stages are short we granted our app call this gc() when the GameScene is paused, quit or stage complete, anywhere where there is no excessive animation.
Preparing characters upfront did not sooth the hiccups, because the texts were dynamic and we could not prepare all possible characters to keep the System.gc() in this method, but honor it later.
Indeed preparing the letters upfront does not trigger GC_EXPLICIT, as it is described in the answer provided by the OP.
EDIT:
After some research, another thing that caused < 60fps, was the SoundPool, we should have playing a sound with volume 0f,0f and looping, in order to prevent the SoundPool reset to idle state and rearm again.

unexpected android system call makes smooth display of scrolling graphic stutter

I am currently writing an app that should display a real time measurement curve in a scrolling fashion (think ECG recorder or oscilloscope). An unexpected system call in the UI-Thread makes the display stutter.
The data rolls in via bluetooth. All works fine and the display is reasonably smoothly scrolling with an average update rate of 26 frames/s. But, nevertheless the display is stuttering remarkably.
I used traceview to get more insight and according to traceview the stuttering is the result of a call to android/view/ViewRoot.handleMessage which lasts 131 ms per call on average.
If I dig down further in traceview the cycles are burnt inside android/view/ViewRoot.performTraversals. 92% of these CPU cycles are consumed in mostly recursive calls to android/view/View.measure.
From there it gets complicated due to the recursive call structure. But I can find calls to the onMeasure() method of LinearLayout, FrameLayout and RelativeLayout. The onMeasure() method of each Layout type consumes about the same amount of CPU cycles. Which is very strange since in my activity I use only a simple LinearLayout with just 2 Elements.
I just see no reason on why a supposed re-layout of a LinearLayout with 2 Elements performs calls to non-used Layouts and takes a whopping 131 ms to do that.
Further info:
Platform HTC desire HD with Android 2.3.1.
I use a handler to perform the drawing in the UI thread.
The Layout is a simple LinearLayout with 2 Elements: a custom view and a textField.
The status bar is hidden with getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);.
The drawing is performed on each new block of data, which arrives approx. every 50 ms.
The drawing itself uses a canvas and is performant enough to keep up with the incoming data.
After that long explanation, here are the questions:
What is calling the android/view/ViewRoot.handleMessage? (the calls are relatively equal spaced every 850 ms and have no obvious link (no direct calls, number of calls and relative positions are not linked to the message handler for drawing) to any activity of my Activity)
How can I suppress the calls to android/view/ViewRoot.handleMessage or how can I make them faster (there are just 2 elements in my LinearLayout)
the calls to unused layouts first got me think of the status bar or some hidden activity (e.g. home screen), which may use such layouts. But how come those calls are part of the trace of my activity? As far as I understand the trace should only trace the active process. e.g. the calls of my service which produces the real time data is not part of the trace.
Is there any possibility to trace individual calls to some system components? When I zoom in in traceview I see this call sequence: toplevel -> android/os/Message.clearForRecycle() -> android/os/MessageQueue.nativePollOnce() -> android/os/SystemClock.uptimeMillis() -> com/htc/profileflag/ProfileConfig.getProfilePerformance() -> android/os/Handler.dispatchMessage() -> android/view/ViewRoot.performTraversals()
Off topic: Is there a possibility to export the data which is shown inside traceview (parents-children-CPU time etc.) other than a screenshot?
Ok, I found the reason for the long call to android/view/ViewRoot.handleMessage.
This was indeed caused by my application.
My App has 2 screens (Activities) one with a complicated Layout for status information and the other one the real time display of incoming data.
The data, which comes in over bluetooth contains mixed real time data and status data. When I switch to the real time Activity, I was stopping the status Activity with finish(); after starting the new real time Activity. Unfortunately this is not enough to stop also the message handler, which receives the new status information in the UI thread, and continued to update status data in an invisible and finished Activity. The relayout of this activity caused the stutter of the real time data.
This is now solved. The display scrolling is now reasonable smooth.
Thanks for your patience. May it be useful to anyone who stumbles on this Thread on stackoverflow.
jepo

Categories

Resources