All your update loop does is call something on the main thread, which clearly needs to be synchronized, and can't be performed until the main thread is done being busy. And when there's input to be processed, and the main thread does that, well, you're seeing the expected results. Worst case, -updateFPS gets called less frequently than if it was run by a timer on the main thread.

Moving your rendering to a separate thread only makes sense if your critical sections are short, and you don't do such a silly thing as in the above example.

Well, I simplified it here to absurdity to make a point. Processing input, particularly when the app doesn't even have any defined handlers, should not take 5ms! Is there a way to poll instead? Or disable input handling on the main loop, so it can be handled more smartly/efficiently in a custom runLoop?

What's killing me is that in my actual app, I've got two threads. A render thread pinged at 60hz (limited only by the gpu refresh rate), and an update thread which runs much slower (about 20hz currently) with the render thread interpolating states.

What I'm seeing is that the slower my update thread runs, the worse the per-frame input handling becomes.

For instance, if I artificially inflate the above example with the following code:

... my update takes about 200ms, and touching the screen drops it to 250ms!

That means in a sampling of 200ms of my secondary thread, it has been interrupted enough times to have sucked up 1/4 of the processing time (or 20% of the total time) to do NOTHING!?! Just because I'm dragging my finger around the screen. That makes no sense. Do we have any control over this? I did a bunch of searching, and found some examples where people were able to enumerate the ports for the main run loop and remove them, but those interface don't appear to be exposed in the iPhone SDK.

Just for the sake of sharing what I've seen so far: The way it's done in GLSprite is very roughly how I do things. The timer path works best for me. I've tried doing a separate thread for rendering/updating but unlike a few others around here, my results show roughly the same performance (actually worse by a frame or two per second, using threaded rendering, if anything). My testing was done using an app which I've nearly completed and uses plenty of lit and depth-tested 3D geometry, mixed with plenty of blended sprites.

So not only did threaded rendering do nothing for me, but maybe cost me a hair of performance. Further, it complicated matters if I wanted to use other UIKit views for certain things. I just haven't been able to find any practical advantage to threaded rendering on iPhone vs using the standard timer path ... yet. My sense is that, for best flexibility and convenience, the threaded approach on iPhone probably isn't worth the extra hassle, just for a few frames (if you can find 'em). There are other ways to improve rendering performance for greater gains and less hassle, IMHO.

Also, I've read in a few places where some folks were having terrible problems with input processing, screwing up timing. I have had very few problems with input so I don't know where those issues come from.

If you insist on calling performSelectorOnMainThread:, you're not gonna see improved performance. And, an observed 25% time used for input processing isn't a lot, if you consider the machinery things have to go through.

Clearly my simplified example has failed to communicate the problem. Can maybe someone provide an example using a secondary thread at 100% usage (e.g. not sleeping or blocked for a significant period of its cycle) that does not exhibit a 20% performance drop when dragging your finger on the screen. (Switching the performSelectorOnMainThread to just dumping the frame time to the console via NSLog doesn't change anything - though I'm not familiar with the synchronization issues that NSLog may have. In my actual app, I'm displaying the framerate using OpenGL without crossing any thread barriers fwiw.)

In any case, I cannot possibly see how that's acceptable. Maybe someone can explain the machinery its going through that could possibly explain such a hit. My understanding was the the iphone has a dedicated chip for handling the touchscreen. My assumption from there was that the main thread then maybe gets interrupts for move events, which get pushed onto the runLoop's event queue and handled on the next iteration.

In a single-threaded app using a timer, if your update takes too long, it sounds like it's possible to starve input handling since user events have higher priority than input events.

Moving your update loop to a separate thread should then keep the main thread idle most of the time, and only wake up when a new event (such as dragging your finger on the screen) needs to be handled.

In my actual app, I'm not using performSelectorOnMainThread. Instead, I have a single NSLock which I use when handling input on the main thread.

aleiby Wrote:In any case, I cannot possibly see how that's acceptable.

Losing some measure of performance because of input processing and timing does not seem terribly unacceptable and/or unexpected to me (especially in the higher frequency ranges). It is an iPhone after all, not a desktop... But admittedly, I'm not all that picky about everything.

aleiby Wrote:In a single-threaded app using a timer, if your update takes too long, it sounds like it's possible to starve input handling since user events have higher priority than input events.

I guess, theoretically, but in practice, even if I'm doing a complex scene and bogging down to 20 fps or lower, I'm still getting 60 ticks of simulation and not missing any input (except for maybe a missing touch up on occasion, which I suspect may be my fault in one of my logic routines). I don't have a clue why I've heard others missing input for maybe up to seconds. Maybe they may have set their render timers to an unacceptably high value? I set mine to 60 and do just fine like that.

You are running a tight loop - while (1) effectively. The best solution is to introduce a lock inside the while loop, for 2 reasons. One, it provides synchronisation with events outside your thread, and two, it can force a reschedule.

Eg.

Code:

while (!done)
{
aLock->Lock();
Render();
aLock->Unlock();
}

You also need the lock to prevent touch screen input code from running in the middle of a render cycle (causes all sorts of sideeffects)
eg.

Code:

- (void)touchesBegin
{
aLock->Lock();
do something
aLock->Unlock();
}

I am using a render thread and my frame rate went up 20%, and I do not lose any input.

Click the "% CPU" column twice so the arrow points down to sort by descending order

Select any of your own apps from the Launch Executable drop down

Click record, let it run for 5-10 seconds and click Stop (same button)

Repeat the previous step, but this time make sure you continuously rub the iPhone screen with your finger (to generate move events)

Now, you can compare the two runs by clicking the arrows in the timer pane at the top. What I'm seeing is that when I rub the screen, the loginwindow process is sucking up about 20% CPU (and is idle otherwise).

I don't have any other devices to test this on, so maybe you guys can see if you get similar results and post which device you tried it on.

Anyone know what this process does? There's some mention of it here, but that doesn't really explain what's going on with the iPhone.

I have exactly the same problem with ipod-touch 1st gen whether I use a separate render thread or a main thread timer (I also noticed it's present in 2nd gen ipod-touch but hardly noticeable since the machine is 20% faster than 1st gen).

I contacted apple technical support about this, and they could not give me a solution, other than to put a request in for a feature to control how the OS polls the hardware (similar to how you can control the polling rate of the accelerometer).

try #define kAccelerometerFrequency 0.0
It used to help me a lot. Not with performance of random finger sliding and touching but with the accelerometer which makes everything very laggy if you don't really use it and the kAccelerometerFrequency is not set to 0.0. I used to develop my application on top of CrashLanding and I didn't notice the kAccelerometerFrequency constant so it was set to 100 hz and I had a lot of lags in my app.

thanks for the info godexsoft. I've already disabled the accelerometer by setting a huge udpate interval.

If you look at the crash landing code, setting kAccelerometerFrequency to 0.0 is not quite right since will cause a divide by zero. It might just be luck that the resulting undefined float is stopping the accelerometer:

Off course, this is all a moot point for the actual problem talked about here. Touching the screen on 1st-gen ipod really hits performance. I've found the easier way to show the problem is to simply touch and hold five fingers on the screen (you don't actually have to move your fingers around on the screen).