Forums - Profiling native library

3 posts / 0 new
Last post
Profiling native library
tony.mathew
Join Date: 6 Sep 16
Posts: 1
Posted: Wed, 2016-10-19 18:12

Hi,

 

I am trying to profile my native library, and corresponding android instrumentation apk. I am building my app with debug symbols. Is there a way of getting the profiling results of cpu usage of top functions in my application? This would really help me find the bottle neck functions in my library and optimize them.

 

Thanks,

Tony

  • Up0
  • Down0
Carlos Dominguez Moderator
Join Date: 27 Jul 15
Location: San Diego
Posts: 110
Posted: Fri, 2016-10-21 10:45

Hi Tony,

Snapdragon Profiler doesn't have that feature currently although we are working towards that kind of functionality. That said, as a temporary workaround you could write generically formatted data to the android trace marker event, Snapdragon Profiler will be able to recognize it and show the desired data along side your trace captures. This can be achieved by directly writing formatted strings  to /sys/kernel/debug/tracing/trace_marker with the "tracing_mark_write" format. I'd recommend reading on the format as it supports various types of events (most notably 'C' counter type data and 'B/E' begin/end range markers). Note that this wont give you the statistical information you desire right off the bat so it might require some post processing on your side to get the most used range markers, etc. 

  • Up0
  • Down0
swinston
Join Date: 8 May 15
Posts: 9
Posted: Fri, 2017-01-06 05:24

Hi Tony,

I recently was faced with the same issue and have discovered a wonderful work around.  First Carlos is absolutely right, one needs to write to write to the system trace file at the path he gave.  However, there's one unfortunate caveot, not all production devices have systrace support. The file might not exist on your device; if you're in this case, you're probably on a non N device this should sort you out:

*/

mount -o rw,remount -t debugfs none /sys/kernel/debug

 

If that doesn't work and the file still doesn't exist, you have a rooting/rebuilding kernel with systrace enabled enjoyable experience in your future.

Here's the Java version: https://developer.android.com/studio/profile/systrace.html, there is a NDK version that only works in N+ (ATrace_BeginSection/ATrace_EndSection) but it also only handles the b/e markers that weren't enough for my needs; and very likely wont help you with yours.  The reason why is the B/E section only takes a pid so any end event on any thread in the same pid has the fun side effect of making the nested section tags pretty worthless in most apps.

There's two other types of markers, an async marker 'S'/'F' which you provide the pid and a cookie so it can correctly handle a begin/end along with a 'C' marker that will give you a count.  The count is interesting in that it will render out a nice bar graph (useful for displaying variable data).

Now for the reason for posting this, the Snapdragon Profiler is better at displaying the resulting html files.  It also has an import trace file utility.  The problem that it solves is that the Async tags will display as disjoint items in the html page; when there's a lot of them, it's hard to sift through it.  Snapdragon Profiler will put them in one async tab that you can drill into and find the big outliers.  It's admittedly not ideal and you have to pick and chose your battles carefully as too many 

So what I do is hook up the command line trace file generation tool to our CI / auto unit testing system and use Snapdragon Profiler to view the results, when things go bump; this provides a good way to understand when it went bump.

Here's some example code that works pretty well:

int fileId = open("/sys/kernel/tracing/trace_marker", O_WRONLY);
if(fileId == -1) assert(false);

void nested_begin(const char* markerName) {
   char buf[256];
   int len = sprintf(buf, 256, "B|%d|%s", getpid(), markerName);
   write(fileId, buf, len); 
}

//I'm skipping the rest of the non relevant parts and showing the strings that are possible and what they go with:
void nested_end(){
  int len = sprintf(buf, 256, "E");
}

void counter(const char* counterName, int value) {
     int len = sprintf(buf, 256, "C|%d|%s|%d", getpid(), counterName, value);
}

void async_begin(const char* markerName, int cookie) {
       int len = sprintf(buf, 256, "S|%d|%s|%i", getpid(), markerName, cookie);
}

void async_end(const char* markerName, int cookie) {
      int len = sprintf(buf, 256, "F|%d|%s|%i", getpid(), markerName, cookie);
}

 

Note that you can't use | in any of your character strings or bad things happen.

  • Up0
  • Down0
or Register

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.