Java/Android中查找执行时间大于一秒的方法的最快/最简单的方式

5

我正在尝试找出哪些方法(特别是在主线程上)需要超过一秒钟才能执行。不幸的是,我正在使用DDMS和traceview,但我并不真正理解如何阅读提供的数据。是否有一种简单的方法来查找长时间运行的方法?

11个回答

11

@Jake Wharton刚刚发布了 Hugo,它允许您对方法进行注释并在logcat中接收这些方法的运行时间。


6

每次调用方法时,您可以简单地打印出时间和方法名称。然后,您只需查看前一个时间戳与当前时间戳之间的差异是否大于您想要的时间(例如1秒)。

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

6
您可以使用 SystemClock 类来计算函数调用前后的时间差。
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");

文档: http://developer.android.com/reference/android/os/SystemClock.html

这个链接是关于 Android 操作系统中 SystemClock 类的文档。该类提供了与系统时钟相关的方法。您可以使用该类来测量应用程序执行时间或跟踪事件之间的时间间隔。详细说明和示例请参见上述链接。

1
那种方法唯一的问题是我们必须在每个函数调用中添加这些代码行。 - StackOverflowed

3

关于如何使用traceview的教程,请参考:

traceview

请记住,网络或数据库调用可能需要很长时间,不应在主线程中调用,应使用后台线程或AsyncTask来完成这些调用。

除此之外,您还可以自己编写时间测量辅助方法,类似于以下示例(利用反射并以毫秒返回方法调用时间):

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;
}

(错误代码为-1,这意味着找不到指定参数的方法等)

3
我认为最快的方法就是在调试器中运行程序。随机地暂停程序,然后简单记录暂停时程序所执行的方法即可。
暂停在慢方法中的概率比在快方法中高得多。这意味着程序在暂停时正在执行的方法是较慢的方法。
有关更多信息,请参阅Mike Dunlavey对类似问题的出色解答: https://dev59.com/n3RC5IYBdhLWcg3wOOL1#378024

1
除非我们谈论的是一个或两个方法比其他方法慢得多,否则在我看来,为了获得统计显著结果所需的暂停次数非常高... - Tim B

2
“嗯,没有最快的计时函数方法,但可以精确而简单。

我认为,如果想要精确,微秒可能是最好的选择:


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

返回当前运行的Java虚拟机高分辨率时间源的值,以纳秒为单位。这是从JVM中获取的,不一定是纳秒级别的分辨率。如预期的那样,这是测试函数执行时间最准确的方法。
此方法提供纳秒精度,但不一定提供纳秒分辨率(即值更改的频率)-除了保证分辨率至少与currentTimeMillis()相同外,不做任何保证。

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

您也可以尝试使用断点调试器:http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jdb.html

2

除了日历和系统时钟类外,我喜欢第三个选项: Apache Commons StopWatch

在方法开始时实例化该类并调用StopWatch的start方法,在方法结束时调用其stop方法。

然后toString方法会给出经过的时间。


2

你是否了解StrictMode?它会在主线程上执行重任务时在日志中打印相关信息。报告中包含以毫秒为单位的时间,因此您可以轻松地跟踪导致UI线程冻结的代码。


1
关于您的主类想法,您可以使用junit和上面的建议,通过使用Calendar.getTimeinMillis()或System.getNanoTime()并在方法测试结束时执行substraction。纳秒时间更加适用,因为方法中的毫秒时间可能不存在。您还可以添加来自上述@Hugo方法或其他任何内容。
将junit与您的主要代码结合起来,但通过测试用例运行所有内容以进行调试。由于调试器可能会减慢速度,因此这更加准确。
Junit的好处是它适用于Java中的任何内容,甚至可以测试一定数量的迭代或执行断言。它完全控制您的测试,允许您在方法内测试时间。它被世界各地的公司使用,包括英特尔。此外,它使您的代码保持清洁,消除了大量日志记录需求等,因为它是从单独的类中运行的。
您的代码在测试类中将如下所示:
//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; 

}

1
你使用的开发环境是什么?
你真正需要的是一个性能分析器。为你的开发和测试环境寻找合适的性能分析器,分析结果将告诉你方法调用的频率以及调用所需时间。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接