Quickiest/easiest way to find methods in Java/Android that take a second or more to execute

StackOverflow https://stackoverflow.com/questions/19697822

Вопрос

I am trying to figure out which methods (esp on the Main Thread) take more than a second to execute. Unfortunately I am using DDMS and traceview, but i don't really understand how to read the data provided. Is there an easy way to find long running methods?

Это было полезно?

Решение 4

For a tutorial on how to use traceview:

traceview

Remember that network or db calls can take long time and should not be called on main thread, use a background thread or AsyncTask to complete those calls.

Other than this you could probably roll your own time measuring helper method something like this (this is utilizing reflection and returns the method invocation time in milliseconds):

public static long timeMethod(Method m, Object obj, Object... args) {
    long start = 0, stop = 0;
    try {
        start = SystemClock.uptimeMillis();
        m.invoke(obj, args);
        stop = SystemClock.uptimeMillis();
    } catch (Exception e) {
        return ERROR;
    }
    return stop - start;
}

(Error is just -1, this happens if the method with specified args aren't found etc)

Другие советы

@Jake Wharton just released Hugo which would allow you to annotate methods and receive the running time of those methods in logcat.

You can simply print the time each time you call a method along with the method name. Then you just look to see when the difference between the previous time stamp is longer than however long you would like (1 second)

Calendar c = Calendar.getInstance(); 
int seconds = c.get(Calendar.SECOND);

You can use the SystemClock class to figure out the difference in time before/after a function call.

long time_start = SystemClock.elapsedRealtime();
myFunction();
long time_end = SystemClock.elapsedRealtime();
long diff = (time_end - time_start) / 1000;
Log.i("mytag", "Time Difference: " + diff + " seconds");

Documentation: http://developer.android.com/reference/android/os/SystemClock.html

I think the quickest way is the simply run your program in a debugger. Pause it at random intervals, and then simply noting which method the program was executing when you paused.

The probability you will pause in a slow method is much higher than pausing in a fast method. This means that the methods the program was executing when you paused it are the slow ones.

For more information see Mike Dunlavey's excellent answer to a similar question: https://stackoverflow.com/a/378024/1375762

Along with the Calendar and SystemClock classes, a third option exists that I like: Apache Commons StopWatch

You just instantiate the class at the beginning of your method and call the StopWatch's start method, then call its stop method at the end of your method.

The toString method then gives you the elapsed time.

Well, there isn't a Quickiest way to time functions, but can be precise and easy.

I think if you want to be precise the microseconds can be the best choise:

long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;

Returns the current value of the running Java Virtual Machine's high-resolution time source, in nanoseconds.

So this is obtained from JVM, not necessarily nanosecond resolution. As expected is the most exacly way to test functions execution time.

This method provides nanosecond precision, but not necessarily nanosecond resolution (that is, how frequently the value changes) - no guarantees are made except that the resolution is at least as good as that of currentTimeMillis().

http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime%28%29

Also you can try a Debugger using break points: http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jdb.html

Are you aware of StrictMode? It prints in log every time something heavy is executed on main thread. The report includes time in ms so you can pretty easily track down the code that freezes UI thread.

What development environment etc are you using?

What you are really looking for is a Profiler. Look for a suitable one for your development and test environments and the profiler results will tell you both how often methods are being called and also how long the calls are taking.

As for your main class idea, you could use junit and either the suggestions above by sticking Calendar.getTimeinMillis() or System.getNanoTime() and perform substraction at the end of the method test. Nano time is more appropriate since the amount of time in millis can be nonexistent for a method. You could also add the @Hugo methods from above or anything else you want.

Combine junit with your main but run everything via test cases for debugging reasons as well. Since a debugger can slow things down, this is more accurate.

The benefits of Junit is that it works for anything in Java and can even test a certain number of iterations or perform assertions. It gives full control over your testing, allowing you to test time within methods as well. It is used by companies all over the world including Intel. Furthermore, it keeps your code clean, eliminating a bunch of logging needs and etc because it is run from a separate class.

Your code would look like this following in your test class:

//you could also use @Test(timeout=long)
@Test
public void testMethod()
{
   YourClass test=new YourClass();

   long s=System.getNanoTime();

   //you could call your method directly here as well
   assertEquals("name",50,test.yourMethod());

   s=System.getNanoTime()-s; 

}

There is an inbuilt Android TimingLogger class. https://developer.android.com/reference/android/util/TimingLogger

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top