[android-developers] Touch *extremely* expensive performance-wise

Showing 1-20 of 20 messages
[android-developers] Touch *extremely* expensive performance-wise con.sultan 1/9/09 4:40 AM
Hi guys,

I'm developing a touch-controlled game and have noticed that when I
touch the screen and don't lift my finger off it the game's frame rate
drops in *half*.
My touch-related code does nothing but record the touch event, that
is, setting a few members of an object. No locking, no nothing.

I've noticed that a long time ago and wasn't very concerned because
even with this unreasonable frame drop the game plays at > 25 fps and
is still visually pleasing, but it doesn't look as good as when
playing at full fps.
I'm wondering if anyone knows (especially guys who have developed or
are developing similar games) whether there's something I can do to
make this performance problem go away.
The only thing I've figured out so far is to disable the long press on
the surface view (thinking that Android itself is making something
funny if long press is requested) but it didn't make any difference.

Thanks!
Stoyan

Re: [android-developers] Touch *extremely* expensive performance-wise con.sultan 1/9/09 8:02 AM
OK, I measured how many moves per sec the view gets when I hold my
finger as still as possible.
The result is surprising (I expected more and was hoping that's the
reason for the slow down) and is about 70 moves/second.
I still don't get why the view gets 70 moves/sec if I'm not moving my
finger at all :(
Can anyone shed some light on why touching the device's screen and
holding the finger on it will decrease the speed of my app as much as
*twice*?

Thanks!

Re: [android-developers] Re: Touch *extremely* expensive performance-wise Dianne Hackborn 1/9/09 1:03 PM
The system delivers events as fast as you will process them.  This is a common issue when a game is designed where most of the work is done outside of the main thread -- probably the best solution at this point to to sleep for some number of milliseconds each time you process an event to throttle the delivery rate.  You could also bump up the priority of your game thread -slightly- to give it a bit of an edge over the main thread.

Oh and this is a touch screen.  You are never not moving your finger, it is always moving slightly no matter how still you are.  Add in pressure and size to x and y, and there is something always changing.--
Dianne Hackborn
Android framework engineer
hac...@android.com

Note: please don't send private questions to me, as I don't have time to provide private support.  All such questions should be posted on public forums, where I and others can see and answer them.

Re: [android-developers] Re: Touch *extremely* expensive performance-wise con.sultan 1/9/09 1:22 PM
On Fri, Jan 9, 2009 at 11:03 PM, Dianne Hackborn <hac...@android.com> wrote:
> The system delivers events as fast as you will process them.  This is a
> common issue when a game is designed where most of the work is done outside
> of the main thread

This makes sense to me.

> probably the best solution at this point to to sleep
> for some number of milliseconds each time you process an event to throttle
> the delivery rate.

I do "yield" to the main thread by calling mainActivity.runOnUiThread
w/ a no-op (cached) runnable once per second but I guess that's not
enough. I'll try increasing that to see if it will make a difference.
I'd rather run the game @ 40 fps by losing ~15 fps because of yielding
than losing ~30 fps because of touch event throttling.

> You could also bump up the priority of your game thread
> -slightly- to give it a bit of an edge over the main thread.

I'd rather "control" the priority myself :)

>
> Oh and this is a touch screen.  You are never not moving your finger, it is
> always moving slightly no matter how still you are.  Add in pressure and
> size to x and y, and there is something always changing.

Right, I did forgot about pressure, thanks for pointing that out!

Thanks a bunch Dianne, you've been very helpful!

Cheers,
Stoyan
Re: [android-developers] Re: Touch *extremely* expensive performance-wise Dianne Hackborn 1/9/09 2:49 PM
On Fri, Jan 9, 2009 at 1:22 PM, Stoyan Damov <stoyan...@gmail.com> wrote:
I do "yield" to the main thread by calling mainActivity.runOnUiThread
w/ a no-op (cached) runnable once per second but I guess that's not
enough. I'll try increasing that to see if it will make a difference.
I'd rather run the game @ 40 fps by losing ~15 fps because of yielding
than losing ~30 fps because of touch event throttling.

If I am reading that right, that's not a yield, that is just adding more CPU using work on the main thread. :)  What you want to do is force the main thread to actually stop running for a bit after processing an event, so that it isn't using the CPU and your other thread can run and the window manager doesn't immediately turn around and give you another event with more work to do.
 
I'd rather "control" the priority myself :)

How are you going to control the priority yourself?

Re: [android-developers] Re: Touch *extremely* expensive performance-wise con.sultan 1/9/09 5:14 PM
On Sat, Jan 10, 2009 at 12:49 AM, Dianne Hackborn <hac...@android.com> wrote:
> On Fri, Jan 9, 2009 at 1:22 PM, Stoyan Damov <stoyan...@gmail.com> wrote:
>>
>> I do "yield" to the main thread by calling mainActivity.runOnUiThread
>> w/ a no-op (cached) runnable once per second but I guess that's not
>> enough. I'll try increasing that to see if it will make a difference.
>> I'd rather run the game @ 40 fps by losing ~15 fps because of yielding
>> than losing ~30 fps because of touch event throttling.
>
> If I am reading that right, that's not a yield, that is just adding more CPU
> using work on the main thread. :)  What you want to do is force the main
> thread to actually stop running for a bit after processing an event, so that
> it isn't using the CPU and your other thread can run and the window manager
> doesn't immediately turn around and give you another event with more work to
> do.

Now you got me confused :) but let me 1st explain that by yielding I
meant that the game thread yielded to the UI one.

My confusion (now) is that I thought (after your post) that the main
UI thread was not given enough time to process touch events and the OS
was doing something (more work) because of that and was leaving my app
with less time to work. You're now saying it's the opposite, but that
can't be the problem because before I added the yields, the game
thread was running at full speed and the UI was so unresponsive (e.g.
clicking the Menu button resulted in ANR) that I had to do something
about it and start yielding to the UI thread from the game one
occasionally.

However, I realize that you're not really saying to not let the UI
thread work but to make it unresponsive for a bit every now and then
(after an event is processed) so that the game thread works more and
less context switches (made by Android's thread scheduling mechanism,
not by me marshalling calls) occur. Is that what you're saying?

Now just before I was about to post this, I profiled the game and let
me share some *very* interesting facts about the touch handling.

I ran the game, touched (which triggers the profile start process),
and immediately removed my finger from the screen and let the
profiling finish.
What I saw in Traceview is that 64.7% of the game's time went in
drawing (which is great!), 33.8% in the game's update, and
android.os.Handler.dispatchMessage(Message) takes the funny 0.2% - I'm
mentioning dispatchMessage here because you'll see a DRASTIC change in
a second.

I then ran the game, touched the screen and started moving my finger
without releasing it until the profiling stopped.
What I saw in Traceview is that 49.1% went in the game's update code,
only 9% in the draw code and now for the winner -
Handler.dispatchMessage took 24.7% of the time :O :O :O
This only makes me think that my assumption that the layers below the
app are doing something more than expected :(
I'm yet to find out why would the update vs draw time is 49% to 9%
(maybe locking the canvas and event handling on the UI thread are
somewhat related???), but having an overhead of 25% just because I'm
touching the screen is too much for me.

Cheers

>
>>
>> I'd rather "control" the priority myself :)
>
> How are you going to control the priority yourself?

Now that you understand what I meant by yielding (that is, not to the
OS but from the game to the main/UI thread) I guess that question is
moot.

Cheers
Re: [android-developers] Re: Touch *extremely* expensive performance-wise con.sultan 1/9/09 5:51 PM
I'll add that the time consumed by my view's onFingerMove is 2/3 of
the time to call (MotionEvent.getAction + .getX() + .getY()) - that
is, I'm pretty sure I'm not doing anything funny in my touch event's
handler.
Re: [android-developers] Re: Touch *extremely* expensive performance-wise con.sultan 1/10/09 1:19 PM
Dianne, I want to thank you again for your advice - it actually
helped. I process at most 10 touch movement events per second (good
enough for the app) and sleep the UI thread after the moves - this did
boost the second thread enough so that most of the app's time is spent
in physics updates and drawing.

Thanks again,
Stoyan
Re: [android-developers] Re: Touch *extremely* expensive performance-wise Dianne Hackborn 1/10/09 6:25 PM
Thanks, glad to hear it helped.  Sorry I was slow responding to your last detailed message.

Fwiw, you should generally avoid trying to directly control scheduling.  Let the kernel schedule the threads as needed; the only issue you had here was that your main thread was using as much CPU as it could get, since it was continually processing touch events, so the kernel would schedule 50/50 between that and the game thread.  Simply reducing the work being done by the main thread (by our little hacky sleep solution) is probably the best way to fix things.
Re: Touch *extremely* expensive performance-wise Jon Colverson 2/13/09 5:31 AM
On Jan 11, 2:25 am, "Dianne Hackborn" <hack...@android.com> wrote:
> Fwiw, you should generally avoid trying to directly control scheduling.  Let
> the kernel schedule the threads as needed; the only issue you had here was
> that your main thread was using as much CPU as it could get, since it was
> continually processing touch events, so the kernel would schedule 50/50
> between that and the game thread.  Simply reducing the work being done by
> the main thread (by our little hacky sleep solution) is probably the best
> way to fix things.

Thank you so much for this thread! It's very very helpful to me.

In my game I was getting 85 touch events per second, but I only use 1
per frame so what I've done is to synchronize my game thread with the
UI thread using Object.wait(1000L) at the end of my onTouchEvent().
The game thread uses notify() and then yields once per frame so that
the UI thread can fetch another event, so it effectively turns it into
a polling model. So now I'm getting 60 touch events per second, which
doesn't sound that different from 85, but the regularity does make a
substantial difference to the smoothness of my frame rate.

Thanks again!

--
Jon
Re: Touch *extremely* expensive performance-wise Zombies and Robots 2/18/09 11:00 PM
I am also developing games which may make heavy use of onTouchEvent(),
so this thread looks very helpful to me as well.

I've been trying to follow everything you guys have been talking
about, but I must admit that after trying several ways of implementing
what you suggest, I still haven't been able to achieve any positive
results.  Could one of you provide some example code?  Specifically,
I'd like to know how to go about making the main/UI thread sleep.  If
it's applicable to my games, it would also be nice to know how to set
up a polling model like Jon implemented.

Of course, I greatly appreciate any help!
Re: [android-developers] Re: Touch *extremely* expensive performance-wise con.sultan 2/19/09 1:33 AM
Here's a hint - override public boolean dispatchTouchEvent(MotionEvent
ev) instead of onTouchEvent - this *does* save quite a few cycles.
You sleep using whatever you find more appropriate - Thread.sleep for
interruptible sleep or SystemClock.sleep for non-interruptible one.

HTH,
Stoyan
Re: Touch *extremely* expensive performance-wise Jon Colverson 2/19/09 5:39 AM
On Feb 19, 7:00 am, Zombies and Robots <caecus...@gmail.com> wrote:
> I've been trying to follow everything you guys have been talking
> about, but I must admit that after trying several ways of implementing
> what you suggest, I still haven't been able to achieve any positive
> results.  Could one of you provide some example code?  Specifically,
> I'd like to know how to go about making the main/UI thread sleep.  If
> it's applicable to my games, it would also be nice to know how to set
> up a polling model like Jon implemented.

Here's what my code looks like. On the UI thread:

public boolean onTouchEvent(MotionEvent event) {
    // Store event somewhere the game thread can see it:
    // ...

    synchronized (someObject) {
        try {
            someObject.wait(1000L);
        } catch (InterruptedException e) {
        }
    }

    return true;
}

and on the Game thread:

void myGame() {
    while (!stopping) {
        // ...

        // Get a touch event:
        synchronized (someObject) {
            someObject.notify();
        }
        Thread.yield();

        // ...
    }
}
Re: Touch *extremely* expensive performance-wise Zombies and Robots 2/19/09 11:16 PM
Thank you both!

With those pointers, I was able to figure out and implement working
versions of both techniques.  Now I just have to decide which one I
like better and finish writing my game...
Re: [android-developers] Re: Touch *extremely* expensive performance-wise suhas gavas 2/20/09 1:41 AM
hi zombies and robots,
plz let me the solution to improve touch event performance
I have got stuck because of the sam

regards,
suhas
Re: Touch *extremely* expensive performance-wise MrSnowflake 3/10/09 11:26 AM
I have a question about this: While sleeping the ui thread works,
would it also work to wait() the main thread and notify() it when the
new frame 'starts'?

On 20 feb, 10:41, suhas gavas <suhas.ga...@gmail.com> wrote:
> hi zombies and robots,
> plz let me the solution to improve touch event performance
> I have got stuck because of the sam
>
> regards,
> suhas
>
> On Fri, Feb 20, 2009 at 12:46 PM, Zombies and Robots <caecus...@gmail.com>wrote:
Re: [android-developers] Re: Touch *extremely* expensive performance-wise con.sultan 3/10/09 11:48 AM
sure, it should work - I think someone has already done that
Re: Touch *extremely* expensive performance-wise MrSnowflake 3/11/09 6:38 AM
But won't it affect other Activity stuff and life cycle functions and
such?

On 10 mrt, 19:48, Stoyan Damov <stoyan.da...@gmail.com> wrote:
> sure, it should work - I think someone has already done that
>
>
>
Re: Touch *extremely* expensive performance-wise Streets Of Boston 3/11/09 7:22 AM
I would think so too.

As soon as you execute wait statements in your main message-
dispatching thread (e.g. sleeps, waits, waiting for I/O, long lasting
loops, joins, etc.), you run the risk of the application getting
unresponsive. Android may pop up a message telling the user that the
application is not responding giving the user the choice to wait or
force-close.

In this case, the longest wait is only a second, after which the
onTouchEvent returns, but still....
> > >> > like better and finish writing my game...- Hide quoted text -
>
> - Show quoted text -
Re: [android-developers] Re: Touch *extremely* expensive performance-wise Dianne Hackborn 3/11/09 11:13 AM
The ANR dialog is shown when you aren't responsive for 5 seconds.  We should be talking about waiting for ~20ms only for motion events.  These are in completely different realms.