So, I have one problem, which I can't solve. My app used over 45% of cpu samsung SII. I think the main reason is postDelayed.
Here is part of my code:
Handler a=new Handler();
a.post(new Runnable(){
#Override
public void run() {
Calendar cal = Calendar.getInstance(Locale.US);
cal.setTime(curr);
Format formatter = new SimpleDateFormat("\r EE \n d");
int currentDOW = cal.get(Calendar.DAY_OF_WEEK);
cal.add(Calendar.DAY_OF_YEAR,(currentDOW*-1)+i+2);
den.setText(formatter.format(cal.getTime()));
}
a.postDelayed(this,400);
});
So, this is part of my code, it is work, but I think, it is the main reason of high CPU usage. Please help me! Thank you!
you could optimize the code a bit , but i suspect that you simply don't stop the updating when you don't need to , so more and more updates are being accumulated .
as an example , if you change the orientation , it will add more events of the previous activitiy (which was destroyed) and you end up with double the rate of updating .
I had this problem. My app was using around 60% CPU time until I added the following code to my run() method in my worker thread:
#Override
public void run()
{
while( _running )
{
// do usual stuff
// ...
// ** add the following to the end of your loop **
try
{
Thread.sleep( 5 );
}
catch( InterruptedException e )
{
_running = false;
/* at least we tried */
}
}
}
It now uses ~8% CPU with no noticeable difference.
Experiment with the value '5'. I've added an app setting to allow the user to balance better graphics (i.e. number lower than 5) with better battery usage (number higher than 5).
Related
So, I borrowed a timer approach from this excellent post:
Android timer? How-to?
which was very well-written and well-upchecked. However, I find that it fires approximately every 106-114msec, not the desired 100msec. Does this make sense, or does it seem slow? If I wanted to make this closer to an exact 100msec (I am using it in some places to measure durations), what change should I make?
My code is below
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
TickTimer_Elapsed();
timerHandler.postDelayed(this, 100);
}
};
void TickTimer_Start() { timerHandler.postDelayed(timerRunnable, ); }
void TickTimer_Stop() { timerHandler.removeCallbacks(timerRunnable); }
void TickTimer_Elapsed()
{
m_FSM.Tick_10Hz(); // actually a bit slower than 10Hz
}
Timer is overloaded term in English, meaning either a device that measures time (e.g. a stopwatch), or a device that triggers after a time (e.g. egg timer).
In Android, the timer is for the latter only, and it does not promise absolute accuracy.
"I am using it in some places to measure durations"
In real life, to tell how much time has passed, you would not to watch a clock and count the seconds ticking by! You'd get nothing else done in that time. An efficient way would be to look at the clock just twice and subtract the two times. The same is true with computers:
e.g:
long startTimeMs = System.currentTimeMillis();
Later:
long durationMs = System.currentTimeMillis() - startTimeMs;
In a sort-of-working application I see this monstrous code:
class SomeUglyClass extends Thread {
ArrayList<SomeData> someDataStructure = new ArrayList<SomeData>();
Handler mHandler = new Handler() {
// a lot
// writing to someDataStructure
}
public void run() {
int some_count, ...;
while(true) {
// a lot
// r/w access to someDataStructure
try {
Thread.sleep(1, 0);
} catch (Exception e) {
break;
}
}
} // end of run(), total 500 lines of code
} // end of SomeUglyClass, total 4K lines of code
Maybe you already see the problems with this code. If not, here they are:
mHandler is attached to the UI thread (because it is created by the thread that loads the class, which is the main thread)
there's no looper (which is fact is the bug)
the thread wastes CPU time and drains the battery
someDataStructure is not thread-safe, but synchronizing elementary access operations will not help; synchronizing large blocks of code in a endless loop will likely block the guarded resource and make it unavailable for other threads; finally, it is not only someDataStructure, the whole class is based on the assumption that only one thread can run its code.
I cannot just add the looper, because the endless loop in run() has to be run, while Looper.loop(); also is an infinite loop. One thread cannot run two infinite loops.
Despite this epic architectural fail, the code is really doing something, it cannot be re-written at once, it is 4K lines of code, and often I can only guess what the code really does.
I need to refactor it. It should be a sequence of small steps preserving the functionality.
How do I refactor this terrific code?
You should try separation of concerns: try first to divide the whole class into many smallest one, each one responsible for doing/dealing with exactly one thing.
You may have something for data Access (read/write data), service (isolated business logic), and the UI. You may use event bus to decouple between objects (consider otto) and may be dependency injection (consider Dagger).
This process of separation will help you understand what each piece of code is doing and also the dependencies between the different parts, thus making writing unit/integration tests much easier.
Add lots of tests, use version control and then work as slowly as you need to.
The 1st step has been to change:
public void run() {
int some_count, ...;
while(true) {
// a lot
// r/w access to someDataStructure
try {
Thread.sleep(1, 0);
} catch (Exception e) {
break;
}
}
}
to:
#Override
public void run() {
Looper.prepare();
mHandler = new MyHandler();
mHandler.post(run_step);
Looper.loop();
}
Runnable run_step = new Runnable() {
int some_count, ...;
#Override
public void run()
{
//while(true) {
// a lot
// r/w access to someDataStructure
mIntoThreadHandler.postDelayed(this, 1);
//}
}
}
This preserves the functionality but still wastes CPU time. The urgent bug has been fixed, and the issue has been closed; I could not sell "must refactor to kill monstrous code" to my management, but I could sell "this can work faster if I refactor," so a new separate issue has been opened. UGH!
PS no chance to sell "lots of tests".
I am trying to calibrate an accelerometer, but I can't obtain the 6 sample values at 6 different acceleration readings required for the calibration. PreliminaryW is a double[6][3] array made to fill those sample values. It is 6 by 3 because each acceleration reading has an x, y, and a z component.
I am planning to sample them by pressing a button at the 6 different acceleration readings. This button makes "calibrate" true.
I ofcourse, first make "calibrating" true to start this thread.
For some unfathomable reason, preliminaryW[i] = currentAcc seems to be filling up from 0 to i with the same value instead of just i. I made sure that the currentAcc is different every time I press the "calibrate" button.
What is wrong with my code?
public synchronized void run() {
Log.d(TAG, "+ in Calibrator thread +");
int i = -1;
while (calibrating) {
if (calibrate) {
i = i + 1;
calibrate = false;
preliminaryW[i] = currentAcc;
if (i == 5) {
calibrating = false;
}
}
}
}
I'm not very familiar with the inner-workings of the accelerometer, and it's hard to decide why it's not working without seeing more of the code. For example, can you be sure that there's only one instance of the Thread, or are you creating multiple instances?
Why does this need to be in a Thread?
Looping like that is not good practice either, you should use wait/notify if you absolutely need a Thread. (more info at http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html)
I've drafted a class that does approximately what you want, but doesn't use threading. You could create a Calibrator and then call performCalibration() with each new value:
class Calibrator{
int count = 0;
double[][] preliminaryW = new double[6][3];
public void performCalibration(double[] currentAcc){
preliminaryW[count] = currentAcc;
count++;
}
}
without the Thread and "busy loop", you might be able to omit those flags for 'calibrate' and 'calibrating' which would certainly help debugging as well.
Good Luck!
I am a beginner and I want a complete example in LibGDX how to limit the framerate to 50 or 60. Also how to mangae interpolation between game state with simple example code
e.g. deWiTTERS Game Loop:
#Override
public void render()
{
float deltaTime = Gdx.graphics.getDeltaTime();
Update(deltaTime);
Render(deltaTime);
}
There is a Gdx.graphics.setVsync() method (generic = backend-independant), but it is not present in 0.9.1, only in the Nightlies.
"Relying on vsync for fixed time steps is a REALLY bad idea. It will break on almost all hardware out there.
See LwjglApplicationConfiguration, there's a flag in there that let s use toggle gpu/software vsynching. Play around with it." (Mario)
NOTE that none of these limit the framerate to a specific value... if you REALLY need to limit the framerate for some reason, you'll have to handle it yourself by returning from render calls if xxx ms haven't passed since the last render call.
As a complete game engine that LibGDX is, it handles things like this itself. You can configure this at the start of your game, at least with the latest nightlies.
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "Example";
cfg.useGL20 = false;
cfg.width = 800;
cfg.height = 480;
cfg.vSyncEnabled = true;
cfg.foregroundFPS = 60;
new LwjglApplication(new ExampleGame(), cfg);
}
Now your render loop will be limited to 60 calls per second. As to the actual implementation, you should use a Game and Screens. The Screen interface already has a render method which might look like this:
public void render(deltaTime )
{
...
updateAllEntities(deltaTime);
...
renderAllEntities(deltaTime);
...
}
There is only the render method being called by LibGDX, but you can split up your game logic update and the rendering yourself like in the example above.
I have a little problem with ChangeableText in AndEngine. I want to know how to update it's text without freezing the screen? For now I'm using this way, but it's freezing my phone for maybe 2-3 seconds :
private void removeFace(final Sprite face) {
hm = getIconNames();
if(face.getUserData().equals("petrol")){
elapsedText.setText(hm.get(25));
final PhysicsConnector facePhysicsConnector = this.mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(face);
this.mPhysicsWorld.unregisterPhysicsConnector(facePhysicsConnector);
this.mPhysicsWorld.destroyBody(facePhysicsConnector.getBody());
this.mScene.unregisterTouchArea(face);
this.mScene.detachChild(face);
} else {
}
System.gc();
}
Any ideas how to do that?
Remember that when you detachChild you should do this in thread because if you don't it can causes errors. Use this construction
runOnUpdateThread(new Runnable(){
#Override
public void run() {
if(yourSprite.hasParent())
scene.detachChild(yourSprite);
}});
You can put there all code if you want then your phone shouldn't freez
private void removeFace(final Sprite face) {
runOnUpdateThread(new Runnable(){
#Override
public void run() {
hm = getIconNames();
if(face.getUserData().equals("petrol")){
elapsedText.setText(hm.get(25));
final PhysicsConnector facePhysicsConnector = this.mPhysicsWorld.getPhysicsConnectorManager().findPhysicsConnectorByShape(face);
this.mPhysicsWorld.unregisterPhysicsConnector(facePhysicsConnector);
this.mPhysicsWorld.destroyBody(facePhysicsConnector.getBody());
this.mScene.unregisterTouchArea(face);
this.mScene.detachChild(face);
} else {
}
System.gc();
}});
}
Thats probably because you are fetching some information while setting the text.
What you should do is, get your
String hm = hm.get(25); //What ever the correct object is or variable. im guessing its a string or int.
Then
pass it to the Changeable text to be set.
elapsedText.setText(hm); //If its a int make sure you do String.valueOf(hm);
The only 3 methods here that have the possibility to take long are getIconNames() and get(), and System.gc()
The others are usually methods that return immediately, or have a very low complexity. For example, getPhysicsConnectorManager() returns immediately. findPhysicsConnectorByShape, unregisterPhysicsConnector, unregisterTouchArea and detachChild all have complexity of O(n), (And most of the others methods also have complexity of O(1) or O(n)).
I recommend you to look in the LogCat and when System.gc() is called, you will see a Log.i (blue) message of the tag of dalvikvm which will begin with GC_EXPLICIT and will give you some information about how long did the garbage collection took, etc....
If that GC call isn't taking the time, it must be your 2 methods, getIconNames() and hm.get(). You can put a Log.d message after each code line, which will write the last code line executed. This way you can follow the times.