Thursday, November 12, 2009

native and java performance on android

A lot of times when I saw someone heard that the main stream developing language on android platform is java, his first response would be "really? what about performance?". I've seen lots of similar responses when talking about c++ and c# on normal pc. Personally, I don't think argue about this question without a context makes any sense.
In most of situations, manged framework like c# and java suffice. How many times in your life do you have to implement a super powerful server that is capable of handling like one billion requests a time? Does the difference in performance really bother you? I don't think so. What play more important roles are: elegance, maintainability, clearness and number of bugs. And in a lot of situations, managed framework run at commensurate speed with c/c++ code. At least their order of growth are at the same level.
Back to the question itself. Is there significant performance difference between native and java code on android? Just see in action. The ensuing two code snippets will calculate the sum from 1 to 10,000 for 10,000 times in c and java respectively.



1 #include
2 #include
3
4 int main ( int argc, char *argv[] )
5 {
6 int i = 0, j = 0;
7 FILE *f = fopen("/data/perf_c.log", "a");
8
9 int rc = 0;
10
11 time_t t;
12 time(&t);
13 fprintf(f, "Start on: %s\n", ctime(&t));
14
15 for(i = 0; i < 10000; ++i)
16 {
17 for(j = 0; j < 10000; ++j)
18 rc += j;
19 rc = 0;
20 }
21
22 time(&t);
23 fprintf(f, "End on: %s\n", ctime(&t));
24 return 0;
25 } // ---------- end of function main ----------




1 package com.rmd;
2
3 import java.io.FileNotFoundException;
4 import java.io.FileOutputStream;
5 import java.io.PrintStream;
6 import java.text.SimpleDateFormat;
7 import java.util.Date;
8
9 import android.app.Activity;
10 import android.content.Context;
11 import android.os.Bundle;
12 import android.util.Log;
13
14 public class main extends Activity {
15 /** Called when the activity is first created. */
16 @Override
17 public void onCreate(Bundle savedInstanceState) {
18 Log.v("perf_test", "before loop");
19 try {
20 FileOutputStream fos = this.openFileOutput(
21 "perf_java.log", Context.MODE_APPEND);
22 int rc = 0, i, j;
23 PrintStream ps = new PrintStream(fos);
24 Date dt = new Date();
25 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss");
26 ps.printf("start on\t" + sdf.format(dt) + "\n");
27 for (i = 0; i < 10000; ++i) {
28 for(j = 0; j < 10000; ++j)
29 rc += j;
30 rc = 0;
31 }
32 dt = new Date();
33 ps.printf("end on\t\t" + sdf.format(dt) + "\n");
34 ps.close();
35 } catch (FileNotFoundException ex) {
36 Log.e("log_perf_test", "can't open file\n" + ex.getMessage());
37 }
38 Log.v("perf_test", "after loop");
39
40 super.onCreate(savedInstanceState);
41 setContentView(R.layout.main);
42 }
43 }




Having run these applications on android 1.5, we got following result:

start on: Wed Nov 11 12:13:51 2009
end on: Wed Nov 11 12:13:59 2009
total: 8 secs

start on 2009/11/11 09:12:30
end on 2009/11/11 09:13:27
total: 57 secs

The java app has been compiled in release mode for better optimization. And GC should not kick in since I only used auto variables in the sample. So I really didn't expect to see such a huge difference.
Though the performance diffs a lot, I still consider java to be the first priority choice when developing user applications. It has very convenient APIs, powerful presentation framework and great debugging support. And we still can turn to native code for extremely performance sensitive components which java can't satisfy. The official document also states that the performance of native method is 10-100X fater than java, and it suggests use native methods for performance optimization.

2 comments:

Tony said...

Interestingly, because Android 1.6's Dalvik seems to start up faster on my G1 than Sun's latest JVM on my much beefier desktop, apps actually *feel* faster on my phone than on the JIT-enabled JVM on my desktop. For small apps that I just want to use for a few seconds, startup time has a huge impact on user-percieved performance and it looks like Android got at least that right.

rxwen said...

Hi Tony,

I'm also surprised to see the huge performance gap. But the comparison just reveals the relative relationship of java app to native app. Your personal user experience, though not as precise, is a absolute standard that better reflect if the performance is acceptable. As I stated, java application "suffices".