简体   繁体   English

在 Java/Android 中查找需要一秒钟或更长时间执行的方法的最快捷/最简单的方法

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

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.不幸的是,我正在使用 DDMS 和 traceview,但我并不真正了解如何读取提供的数据。 Is there an easy way to find long running methods?有没有一种简单的方法可以找到长时间运行的方法?

@Jake Wharton 刚刚发布了Hugo ,它允许您在 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)然后,您只需查看上一个时间戳之间的差异何时比您想要的时间长(1 秒)

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.您可以使用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");

Documentation: http://developer.android.com/reference/android/os/SystemClock.html文档: 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有关更多信息,请参阅 Mike Dunlavey 对类似问题的出色回答: https : //stackoverflow.com/a/378024/1375762

For a tutorial on how to use traceview:有关如何使用 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.请记住,网络或数据库调用可能需要很长时间,不应在主线程上调用,请使用后台线程或 AsyncTask 来完成这些调用。

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) (错误只是-1,如果没有找到指定参数的方法等,就会发生这种情况)

Along with the Calendar and SystemClock classes, a third option exists that I like: Apache Commons StopWatch除了 Calendar 和 SystemClock 类之外,还有第三个我喜欢的选项: 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.您只需在方法开始时实例化类并调用 StopWatch 的 start 方法,然后在方法结束时调用其 stop 方法。

The toString method then gives you the elapsed time.然后 toString 方法为您提供经过的时间。

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.返回正在运行的 Java 虚拟机的高分辨率时间源的当前值,以纳秒为单位。

So this is obtained from JVM, not necessarily nanosecond resolution.所以这是从JVM获得的,不一定是纳秒级的分辨率。 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().此方法提供纳秒精度,但不一定提供纳秒分辨率(即值更改的频率)- 除了分辨率至少与 currentTimeMillis() 一样好外,不做任何保证。

http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#nanoTime%28%29 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您也可以使用断点尝试调试器: http : //docs.oracle.com/javase/7/docs/technotes/tools/windows/jdb.html

Are you aware of StrictMode ?你知道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.该报告包括以毫秒为单位的时间,因此您可以非常轻松地跟踪冻结 UI 线程的代码。

What development environment etc are you using?您使用的是什么开发环境等?

What you are really looking for is a Profiler.您真正需要的是 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.至于您的主要类想法,您可以通过粘贴 Calendar.getTimeinMillis() 或 System.getNanoTime() 并在方法测试结束时执行减法来使用junit和上述建议。 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.您还可以从上面添加 @Hugo 方法或任何您想要的方法。

Combine junit with your main but run everything via test cases for debugging reasons as well.将 junit 与您的 main 结合,但出于调试原因也通过测试用例运行所有内容。 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. Junit 的好处是它适用于 Java 中的任何东西,甚至可以测试一定数量的迭代或执行断言。 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.有一个内置的 Android TimingLogger类。 https://developer.android.com/reference/android/util/TimingLogger https://developer.android.com/reference/android/util/TimingLogger

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM