Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interpreting Multicore Performance Trace (Eclipse/Android)

I'm working on an android game, and I started noticing a little sluggishness during development so I wanted to try to utilize multithreading for fun and learning.

My application has 3 threads:

  1. UI thread (should be mostly idle)
  2. Game Logic Thread
  3. Graphics Thread

I minimized the critical section between threads 2 and 3 as best I could, with the idea that the game logic could update independently of the rendering thread, and then at the end of both threads I could have a short as possible window where I push all the graphics updates from the logic thread to the game loop. This should allow the two threads to work independently for a good majority of the time. In theory sounds like a performance win.

However once I got around to implementing, my performance took a big dive. It much worse than before, one loop of updating and rendering is taking like 50 ms (20fps), so it looks like garbage. This is just rendering some 20 triangles and maybe 20 textured quads, a really simple workload (I afraid to think of what it will be when I implement proper graphics).

Anyway I took a DDMS trace in android to profile where things were going wrong or could be improved.

trace1http://i.stack.imgur.com/DDUYE.png

This is a view of roughly 3 frames of my game. So far it seems to be doing roughly what I expected. The parts that are highlighted in blue is the locked section, which looks about right (keeps the glThread mostly waiting while it is locked). However once I unlock it I should see both threads working simultaneously, and it looks like they are, but if I look closer:

trace2http://i.stack.imgur.com/vukXQ.png

I'm doing my development on a dual core phone, but if I understand the trace right it doesn't look like it's ever doing anything in parallel, and what's worse it appears to be switching the active thread hundreds of times per millisecond! (unless I'm interpreting this incorrectly). All this context switching seems like it would be awful for performance, so I'm not sure why it would want to switch back and forth so fast.

So after my long winded explanation, I'm wondering a few things:

  1. Is my understanding correct, that the filled rectangles in the trace are the active threads, and the colored lines are sleeping threads? Otherwise what do they mean?
  2. Why don't I ever see my threads running simultaneously on a supposedly dual core phone?
  3. Why is it switching active threads so rapidly?
  4. In DDMS I get the warning "WARNING: a debugger is active; method-tracing results will be skewed". Is this something to worry about? How can I get rid of this warning? (I launced app via Run, not via Debug if it makes a difference)
like image 398
Tim Avatar asked Mar 08 '12 04:03

Tim


2 Answers

Very nice question, let me start with answers:

  1. You have mixed up threads/methods/activeMethod. Each line in traceview is thread (and if you named your threads, you'll see it's name on left side, like "GL Thread", "main", etc..). Rectangles(colored) represents active executing methods inside each thread, while colored lines represents "paused" methods inside thread. By "paused", i mean "method is still executing, but context was switched to some other thread, and when context switched again to this thread, this method will continue to work. In terminology you've used in your question, ye, lines are sleeping thread's methods, and rectangle is active thread executing method. You can find more info about DDMS traceview here.
  2. Distributing threads among cores is another story and heavily depends on underlying Android OS mechanisms. First of all, be sure that target Android OS is started with SMP (Symmetric Multi-Processing) option on, which is default case for multicore phones, i guess :), but i'm not expert in those things. Some words about SMP you can find here.
  3. Thread switching depends on OS Thread/Process scheduler, thread priority, etc. More info about this things you can find in this answers.
  4. Even if you ran application in non-debugging mode, when you connect with DDMS, and do things such Method profiling, you'll activate debugging parts of davlik vm. More details about debugging here, section "Implementation".

Hope you'll find this answer helpful.

like image 130
Tomo Avatar answered Sep 18 '22 14:09

Tomo


Thanks for the question. A full answer by an insider will be helpful to me, too. I'll say what I know.

  • Some (all?) phones have an option to enable/disable the second core. Have you checked that yours is turned on?

  • In my own app I've noticed that merely going from one thread to two (on one core) with no change in total work done causes a factor of 1.5 slowdown, so clearly threading itself has a cost.

  • It's been in the news that Intel is calling Google out on poor implementation of multicore threading:

    http://www.pcworld.com/article/257307/dual_core_processors_wasted_on_android_intel_claims.html

    Your results validate this.

  • One other thing to bear in mind is that multi-core is not multi-processor. You're sharing cache and memory controller bandwidth between cores. One can stall while it waits for the other to finish with a shared resource, in particular for writes on shared cache lines. However this effect ought not account for the single-threading you are seeing.

like image 38
Gene Avatar answered Sep 21 '22 14:09

Gene