5

我试图找出哪些方法(尤其是在主线程上)需要一秒钟以上的时间才能执行。不幸的是,我正在使用 DDMS 和 traceview,但我并不真正了解如何读取提供的数据。有没有一种简单的方法可以找到长时间运行的方法?

4

11 回答 11

11

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

于 2013-12-04T08:46:16.323 回答
6

您可以简单地打印每次调用方法时的时间以及方法名称。然后您只需查看前一个时间戳之间的差异何时超过您想要的时间(1 秒)

Calendar c = Calendar.getInstance(); 
int seconds = c.get(Calendar.SECOND);
于 2013-11-30T18:24:28.950 回答
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

于 2013-12-02T04:48:44.407 回答
3

我认为最快的方法是简单地在调试器中运行你的程序。以随机间隔暂停它,然后只需注意暂停时程序正在执行的方法。

您在慢速方法中暂停的概率远高于在快速方法中暂停的概率。这意味着程序在您暂停时正在执行的方法是慢的。

有关更多信息,请参阅 Mike Dunlavey 对类似问题的出色回答: https ://stackoverflow.com/a/378024/1375762

于 2013-12-02T09:30:12.190 回答
3

有关如何使用 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,如果找不到具有指定参数的方法等,则会发生这种情况)

于 2013-12-02T22:23:35.443 回答
2

你知道StrictMode吗?每次在主线程上执行繁重的事情时,它都会在日志中打印。该报告包含以毫秒为单位的时间,因此您可以很容易地追踪冻结 UI 线程的代码。

于 2013-12-07T13:57:07.953 回答
2

除了 Calendar 和 SystemClock 类,还有我喜欢的第三个选项:Apache Commons StopWatch

您只需在方法的开头实例化该类并调用 StopWatch 的 start 方法,然后在方法的末尾调用它的 stop 方法。

然后 toString 方法会为您提供经过的时间。

于 2013-12-06T21:16:21.810 回答
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

于 2013-12-07T13:47:20.863 回答
1

您使用的是什么开发环境等?

您真正需要的是 Profiler。为您的开发和测试环境寻找一个合适的,分析器结果将告诉您方法被调用的频率以及调用的时间。

于 2013-12-05T10:37:35.613 回答
1

至于您的主要课程理念,您可以使用junit和上面的建议,方法是粘贴 Calendar.getTimeinMillis() 或 System.getNanoTime() 并在方法测试结束时执行减法。纳米时间更合适,因为以毫秒为单位的时间量对于一种方法来说可能是不存在的。您还可以从上面添加@Hugo 方法或您想要的任何其他方法。

将 junit 与您的 main 结合起来,但出于调试原因也通过测试用例运行所有内容。由于调试器可以减慢速度,因此更准确。

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; 

}
于 2013-12-07T18:09:39.380 回答
0

有一个内置的 AndroidTimingLogger类。 https://developer.android.com/reference/android/util/TimingLogger

于 2020-03-27T07:03:39.503 回答