Analyzing Display and
Performance with Systrace
Peter.Pan
What is Systrace
• The Systrace tool helps analyze the
performance of your application by capturing
and displaying execution times of your
applications processes and other Android
system processes.
Command Line Usage
• Android 4.3 and higher options
$ cd $(project)/extenal/chromium-trace/
$ python systrace.py --time=10 -o mynewtrace.html –b 2048 sched gfx view wm
ATRACE
• Path
– frameworks/native/cmds/atrace/atrace.cpp
• Define (form system/core/include/cutils/trace.h)
– #define ATRACE_TAG ATRACE_TAG_GRAPHICS
• Function
– ATRACE_CALL()
• Variables
– ATRACE_INT(“Name”, Value);
– ATRACE_INT64(“Name”, Value64);
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
…
Void Function(){
ATRACE_CALL();
int value = 0;
value = Random();
ATRACE_INT(“RandomValue”, value);
}
…
GUI
Finder
CPU infor.
Control bar
Surceflinger
Other processes
Detail
Timeline
Operation
Keyword
Shortcut:
W: Zoom In
S: Zoom Out
A: Pan left
D: Pan right
CPU Scheduling
• $ python systrace.py --time=10 -o mynewtrace.html sched gfx view wm freq
Process status
Status:
*Uninterruptable sleep (usually IO)
*Running or runnable (on run queue)
*sleeping
Vsync_On
Add/Remove a listener to DispVsyncSource.
Vsync_On
@EventThread.cpp
Vector< sp<EventThread::Connection> EventThread::waitForEvent(…){
…
if (timestamp && !waitForVSync) {
disableVSyncLocked();
} else if (!timestamp && waitForVSync) {
enableVSyncLocked();
}
…
}
@Sufaceflinger.cpp
virtual void setVSyncEnabled(bool enable) {
if (enable) {
status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast<DispSync::Callback*>(this));
…
ATRACE_INT("VsyncOn", 1);
} else {
status_t err = mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));
…
ATRACE_INT("VsyncOn", 0);
}
}
VSYNC
DispVsyncSource produces the Vsync signal.
Vsync
@DispSync.cpp
virtual bool threadLoop() {
while (true) {
…
if (callbackInvocations.size() > 0) {
fireCallbackInvocations(callbackInvocations);
}
…
}…
}
@Surfacefliger.cpp
virtual void onDispSyncEvent(nsecs_t when)
{
sp<VSyncSource::Callback> callback;
{
Mutex::Autolock lock(mMutex);
callback = mCallback;
if (mTraceVsync) {
mValue = (mValue + 1) % 2;
ATRACE_INT("VSYNC", mValue);
}
}
if (callback != NULL) {
callback->onVSyncEvent(when);
}
}
@DispSync.cpp
void fireCallbackInvocations(…) {
for (size_t i = 0; i < callbacks.size(); i++) {
callbacks[i].mCallback-
>onDispSyncEvent(callbacks[i].mEventTime);
}
}
HW_Vsync0
Need HW Vsync
@HWComposer.cpp
void vsync(int disp, int64_t timestamp) {
…
char tag[16];
snprintf(tag, sizeof(tag), "HW_VSYNC_%1u", disp);
ATRACE_INT(tag, ++mVSyncCounts[disp] & 1);
mEventHandler.onVSyncReceived(disp, timestamp);
…
}
HW_Vsync0
@Surfaceflinger.cpp
void surfaceflinger::onVSyncReceived(){
if (type == 0 && mPrimaryHWVsyncEnabled) {
needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp);
}
if (needsHwVsync) {
enableHardwareVsync();
} else {
disableHardwareVsync(false);
}…
}
@Surfaceflinger.cpp
voidsurfaceflinger::onScreenAcquired(){
…
mEventThread->onScreenAcquired();
resyncToHardwareVsync(true); …
}
@Surfaceflinger.cpp
void surfaceflinger:: onScreenReleased(){
…
if (type== DisplayDevice::DISPLAY_PRIMARY) {
disableHardwareVsync(true);
} …
}
Sufacefliger
QueueBuffer()
DequeueBuffer()/QueueBuffer()
DequeueBuffer() QueueBuffer()
QueueBuffer()/AcquirBuffer()
QueueBuffer()
AcquirBuffer()
+1 -1
QueueBuffer()/AcquirBuffer()
@BufferQueue.cpp
status_t BufferQueue::acquireBuffer(BufferItem *buffer, nsecs_t expectedPresent)
{
…
ATRACE_INT(mConsumerName.string(), Queue.size());
…
}
@BufferQueue.cpp
status_t BufferQueue::QueueuBuffer(BufferItem *buffer, nsecs_t expectedPresent)
{
…
ATRACE_INT(mConsumerName.string(), Queue.size());
…
}
FramebufferSurface
QueueBuffer() AcquirBuffer()
Case study(1)
DeliverInputEvent()
Status change
QueueBuffer()
Case Study(2)
Animator
Case Study(3)
Reference
• http://developer.android.com/tools/debugging/systrace.html
• http://www.curious-creature.org/2012/12/01/android-
performance-case-study/

Analyzing Display and Performance with Systrace