3

We have a library codebase that is being ported to Android. I've already ported it from Windows to iOS successfully. For some reason however the version built by the NDK is about 5-8x slower than the one built and run on my iPhone 5c. I recognize the slowness could simply be the device (a Samsung Galaxy S3) but the consensus here at our shop after discussions is that something else is the major cause.

I'm certain that ndk-build is generating a release version because it does that by default -- you have to explicitly make it do otherwise if desired, either by means of the make file or the command line.

It involves processing camera images, and I've gone so far as to completely stop the camera once it hands a frame to the library for processing. I was originally concerned that by improperly using the camera the Android was hogging resources to the extent that by the time the library methods were called the slowness was inevitable. But it's just a barebones app -- nothing going on but the normal display of camera frames and passing them to the library for processing (2 functions, although 2nd is quite extensive).

I'm generating timing information on a function level in the library -- the same methods are all executing slower, though not always 5-8x, sometimes only 3x.

No other apps are running on the device.

If it is very unlikely that it's simply slow hardware, I could use suggestions on how to attack this problem. Our CTO (a very bright, experienced guy) assures me the Galaxy S3 should be much closer to the iPhone 5 in performance. The source code is identical, only it was built with the NDK rather than Xcode or Developer Studio.

In onPreviewFrame() I launch the AsyncTask that simply makes the call(s) into the library. Some code:

@Override
public void onPreviewFrame(byte[] data, Camera camera) 
{
    if ((imageFormat == ImageFormat.NV21) && (!m_bProcessingInProgress))
    {
        if (data == null)
            return;

        m_bmpGrayScale = null;

        m_bProcessingInProgress = true;  // this indicates that we are processing a video frame
        m_camera.stopPreview(); // halt camera while chewing on pixels

        new ProcessPreviewDataTask().execute(data); // launch AsyncTask
    }
    else
    {
        if (data != null)
            m_camera.addCallbackBuffer(data);
    }
}
Alyoshak
  • 2,696
  • 10
  • 43
  • 70
  • First i have a stupid question. Are you sure, the frame you process are the same size, on iphone 5c and galaxy s3 ? It might be one of the cause for your issue. If not have you tried to do some profiling in your native library ? You can find reference here http://stackoverflow.com/questions/7704704/android-is-there-any-tool-for-profiling-native-code. Hope that helps. – sonic Oct 06 '15 at 08:28
  • @sonic -- Yes, they're the same. Good question though. 1280x720. I'll read that link. – Alyoshak Oct 06 '15 at 12:40
  • How are you handling the camera frames? Copying 1280x720x1.5 bytes around will add significant overhead. Or are your timings strictly on the processing of the camera data itself, after the frame is buffered? – fadden Oct 06 '15 at 15:43
  • Is your code multithreaded? iPhone 5 core are for sure way faster than the S3's. Also, are the CPU core's really maxed out in the S3? An app like 'usemon' may give you an idea of how busy the cores are. Are you using any libraries (OpenCV?), or is it all your code? – user1906 Oct 06 '15 at 16:15
  • @fadden -- timings are strictly on the image processing of the library calls. – Alyoshak Oct 06 '15 at 16:17
  • @user1906 -- I use AsyncTask to call the library. I'll add that code to the question. Don't know if the CPU cores are maxed out. Thx for the tip. No, no other libraries at all. – Alyoshak Oct 06 '15 at 16:19
  • Sorry if I wasn't clear, I meant if you use multiple threads inside your code. Have look at this too: http://stackoverflow.com/a/25647306/1762681 – user1906 Oct 06 '15 at 16:20
  • @user1906 -- No threads whatsoever in the library built by the NDK. And only thread in app is whatever AsyncTask has been implemented to use. – Alyoshak Oct 06 '15 at 16:36
  • If you examine the thread priorities (`adb shell ps -p -t`), you'll find that AsyncTask runs at the lowest possible. It's intended for background processing. If your device is otherwise idle it shouldn't really matter, but generally speaking if you want something to finish quickly you should not start it from AsyncTask. – fadden Oct 06 '15 at 16:49
  • @fadden -- Gee whiz. But what if nothing's going on on the main thread? Won't AsynTask get prioritized then? It's definitely worth my trying to run the task on a plain-jane Java thread just to see. Maybe this is the problem. – Alyoshak Oct 06 '15 at 16:53
  • I doubt it's the problem, but sometimes OEMs will tweak their systems to do things that you wouldn't expect on stock Android. If you really want to know exactly what's going on, you'll need to use systrace. I don't know offhand if that's enabled on the S3, and you will probably need a rooted device to get at the kernel bits. You can find an example here: http://bigflake.com/systrace/ . Official docs start here: http://developer.android.com/tools/help/systrace.html – fadden Oct 06 '15 at 16:59

0 Answers0