In my default view I have:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Debug.startMethodTracing(Environment.getExternalStorageDirectory()+"/PosLogistics.trace", 1000000000);
and do the stop here:
protected void onStop()
{
super.onStop();
Debug.stopMethodTracing();
}
The android target is 2.2. When running on Motorolla 2.3 I can trace 900 ms. When running on Samsung Galaxy (4.0) and Sony Xperia (4.0) the app closes immediately as it starts up. Last entry from logcat is
02-15 05:25:19.940: I/dalvikvm(8740): TRACE STARTED: '/mnt/sdcard/PosLogistics.trace' 976562KB
According to this thread: Traceview maximum record time? the trace is limited by the device RAM. Might explain the Motorolla 900 ms, but what is the problem with the Galaxy and Xperia?
You are trying to allocate 1000000000 bytes ~ 1GB for trace buffer. I don't think any system will allow you to do that. It is for in memory buffer size, not for disk.
See vm/Profile.cpp line 383.
state->buf = (u1*) malloc(bufferSize);
Skip giving a buffer size. That will default it to 8MB, should be enough for your needs.
Related
Our company develops several games for mobile platforms, including Android. We use OpenGL for all visual items, including UI (more technical details are below).
We have received some weird warnings from Google Play Console in Pre-launch report, like “Your app took 20764 ms to launch”. On the video provided with this report, the game took about a second to start.
After some investigation we found that Android Systrace cannot detect OpenGL draws made from another thread. So Pre-launch tests think (wrongly) that our game is super-slow.
Is there some method to notify the system that a frame is drawn? It’s seems that eglSwapBuffers() is not enough.
There’s a link to the same problem with Cocos2d: https://discuss.cocos2d-x.org/t/frozen-frames-warnings-by-google-play-pre-launch-report-for-3-17-cocos-demo-app/42894
Some details
When a new build is published to Google Play Console, some automated tests are performed on different devices. Results of these tests are available in Pre-launch report section of the Google Play Console.
Starting from beginning of April we receive strange performance warnings on some of devices (always the same ones). Two examples:
Startup time: Your app took 20764 ms to launch…
Frozen frames: 33.33% of the frames took longer than 700ms to render
Both problems sound dreadful--would have they be true. But when we examined videos of testing, we could not see any problems. All games started pretty fast and ran without visual stuttering.
Systrace report
This is the picture of systrace showing 5 seconds of our game being started (rectangles were drawn by me).
systrace
As you can see, the systrace have found only 4 frames rendered (the pink rect), which were drawn from the RenderThread. But by some reason Android cannot detect our GL draw calls which are performed in another thread (blue rects).
Pre-launch reports also displays only 3 to 4 frames, each 300-400 ms long.
Initialization code
Our game engine runs all game logic and render code in a separate thread. This is simplified initialization code.
The worker thread is created from our Activity’s onStart() overriden method.
public class MyActivity extends Activity
{
protected Thread worker = null;
private native void Run();
#Override
protected void onStart()
{
super.onStart();
if(worker == null)
{
worker = new Thread()
{
public void run()
{
Run();
}
};
worker.start();
}
}
}
The only thing the thread does is the Run() native function. This function may be resolved into something like this:
void MyActivity::Run()
{
initApp();
while(!destroyRequested())
{
// Process the game logic.
if (activated && window != NULL)
{
time->process();
input->process();
sound->process();
logic->process();
graphics->draw();
}
}
clearApp();
}
As you can see, the worker thread constantly spins the update-and-draw loop. Vsync protects the loop from overperforming. Heavy operations like resource loading are done asynchronously to avoid freezes.
From the user side this approach works just fine. Games are loading fast and go smoothly.
So i was testing my app, and ir ocourred and error in one point, i saw the stack trace and it was on a line that i didn't even change and it was working before. But looking to the stack trace i think the problem is lack of memory.
Here's the line of the error (was in the line setContentView..)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_agencia_figueira);
Button buttonFigueira = (Button) findViewById(R.id.buttonMenu);
buttonFigueira.setOnClickListener(
new Button.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(agenciaFigueira.this, MainActivity.class);
agenciaFigueira.this.startActivity(i);
}
}
);
But one of the lines of the stack trace was : Failed to allocate a 10603020 byte allocation with 4194304 free bytes and 7MB until OOM
If it is lack of memory how can i fix it ? :x
You absolutely need to re-examine your stack traceback ... and possibly add debug statements ... to determine exactly where you're asking for 10MB (and failing). You need to identify the specific resource in question before you can determine a solution.
If you're using an emulator ... then you have the luxury of being able to specify the image's memory size (something you often cannot do with a physical handset). Make sure the emulator has a "reasonable" amount of RAM. 512MB is generally a good number.
Android Studio has excellent tools for checking memory utilization. For example:
https://developer.android.com/tools/debugging/debugging-memory.html
Please post back what you find!
On my xperia ray app fails on start when memsize > 50mb (can't alloc so mush). But when memsize = 50mb, app can work around 5 mins, and then fails with message from marmalade, that not enough memory. So how can i find out how mush memory my app needs in peak?
In my .icf file:
MemSize=200000000
#if resolution < 1080x1920
{ [s3e]DispAreaQ < 2073600 }
MemSize=150000000
#if resolution < 640x854
{ [s3e]DispAreaQ < 546560 }
MemSize=52428800
{}
You need to turn on simulator's view matrix option and look under graphics's memory. Check what's the max size it's using. Although simulator's memory usage is different from device's usage, but it'll give you an idea about what memory size is required.
Edit:-
If you need to have different Memsize for debugging you can use MemSizeDebug too, along with MemSize.
I get a clasical "VM budget excedees memory - out of memory" type error crash report from the Android Market.
I checked the app for memory leaks over and over again. This error happens on a very small percent of total application installs, around 1-2% and it always happens on start-up. The app loads some bitmaps from internal memory for each activity, but does not crash on most devices. I thought all applications had a guaranteed minimum stack size for bitmaps so this should work for every device. Min SDK is 7.
Any reason why ? Does this sound familiar to anyone ?
I had quite a similar problem, and my images were simply too big for some devices.
I have read that you have one image per Activity and I guess this happens when switching from one to another as the newly allocated Drawable cannot fit. What you could do, to save some memory, would be to unload the background image of the Activities that are not shown:
#Override
protected void onResume() {
super.onResume();
Drawable d = loadMyDrawableFromDisk();
setBackgroundDrawable(d);
}
#Override
protected void onPause {
setBackgroundDrawable(null);
super.onPause();
}
It may help as the memory will be freed a few after onPause() is called, and not when the underlying View of your Activity will be unallocated by the system.
I'm checking my app for Memory Leaks/Usage and came across something weird that I've only seen so far in Android 1.6 and 2.1. After clicking around in the app a bit and I run "adb shell dumpsys meminfo" for my application, I see the following:
DUMP OF SERVICE meminfo:
Applications Memory Usage (kB):
Uptime: 34639912 Realtime: 153524709
** MEMINFO in pid 5778 [com.app.myapp] **
native dalvik other total
size: 14336 4679 N/A 19015
allocated: 13971 4139 N/A 18110
free: 280 540 N/A 820
(Pss): 2986 4181 13491 20658
(shared dirty): 972 3948 620 5540
(priv dirty): 2876 3224 10976 17076
Objects
Views: 545 ViewRoots: 4
AppContexts: 32 Activities: 31
Assets: 2 AssetManagers: 2
Local Binders: 43 Proxy Binders: 79
Death Recipients: 2
OpenSSL Sockets: 1
SQL
heap: 91 dbFiles: 0
numPagers: 4 inactivePageKB: 0
activePageKB: 0
Asset Allocations
zip:/data/app/com.app.myapp.apk:/resources.arsc: 119K
As you can see, nothing is getting deallocated/GC'd, the Activities are piling up, the AppContexts, etc. until the app just crashes with an OutOfMemoryError. This doesn't happen on 2.2+.
Can anybody give me some insight into why this is happening? I have a feeling it's either something simple, or it's just something weird with my app, but I'm at a loss as to why this is happening.
FYI, I've reproduced this in a 1.6 and 2.1 emulator, as well as my G1 running 1.6. A recent crash report from a user also shows this, which they were running 2.1 on a Droid Eris. Let me know if any more details/code is needed to help with this.
##UPDATE##
Thanks to the info from momo, I was able to track down some memory leak issues, which drastically cut down on the amount of Activities/AppContexts that would show in the Objects list of meminfo.
The number is now down to around the number of actual activities that are in my application, so it seems that on older versions of Android, it will show the total amount of objects your app is consuming. On newer versions it won't, though that could just be only the case on my test devices.
To get a clear picture on why Activities are held up, I normally use MAT and then look at Path to GC root from the Activity that get stuck.
I've a created a simple project which load simple TestActivity in order to illustrate the process. Below is the code for it:
package com.so;
import android.app.Activity;
import android.os.Bundle;
public class TestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Here are the steps:
Dump the hprof on the running process via DDMS "Dump HPROF File" function
Assuming you have MAT installed, this should bring up the MAT screen
Now filter based on your activity package, for the sample above, it is com.so. Screenshot for this process is below:
Now you want to see if this has a clear path to GC. You do that by right clicking the Activity and show all references as shown below:
You should see that your Activity is held by com.android.internal.policy.impl.PhoneWindow$DecorView and no one else. If this is the a case, you are ok and this Activity will be eventually reclaimed by GC.
Now I will do change my class to include a static variable that will hold its own instance:
package com.so;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
public class TestActivity extends Activity {
static ArrayList memoryLeakList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// create a deliberate static list to cause the leak
TestActivity.memoryLeakList = new ArrayList();
TestActivity.memoryLeakList.add(this);
}
}
And if I run the code hprof with the same steps, I now get the reference of the Activity is held by the ArrayList and not the com.android.internal.policy.impl.PhoneWindow$DecorView signifying that there is possibility of a leak if I don't clean up the array
Now, you don't have to do that for every Activity, what I would do just briefly run the app and then dump the HPROF. You would then again filter by package to get the snapshot of your application. In the initial Histogram, you should be suspicious for any Activity that has number of instances more than one after hitting GC button in DDMS and start investigating from there.
One more note, on my 2.1 phones, I couldn't get the HPROF via DDMS, so I did it through the emulator following these steps:
Go to ./adb shell
Type ps to get the pid of your app process
Type kill -10 , you should see in your logcat that it is dumping the memory to /data/misc
If you get permission denied, make sure you read/write on that folder by doing chmod 777 data/misc
Pull the hprof generated by either using DDMS File Explorer in Eclipse or pull command
Since the hprof is dalvik based, in order to use it with memory profiling tools you need to convert it first via hprof-conv available in the tools directory of your Android SDK installation
Run ./hprof-conv [source dump] [target dump]
Use Memory Analyzer (MAT) to view your process Heap.
http://www.eclipse.org/mat/