如何在NDK中获取计算时间

11

我需要获取我在使用NDK/JNI实现的算法中某些部分的计算时间。

我看过这个问题:Android Get Current timestamp?

我认为我可以用相同的方法来获取JNI调用的计算时间,具体做法如下:

Long start, end, time;
start = System.currentTimeMillis()/1000;
//my native call
end = System.currentTimeMillis()/1000;
time = end - start;
Log.i(TAG, "Time ... (ms): " + time);

但我需要检查本地方法中某些小部分的计算时间。我该怎么办?


你可以在调用方法之前和之后设置日志消息,然后只需使用时间 = 结束 - 开始; 我的意思是在日志消息中打印时间。 - TheFlash
@AllessandroGaietta,你的示例将currentTimeMillis()除以1000... 你想要测量的粒度是秒吗? - mah
@mah 这是一个复制错误,我不想除以1000 ;D - Alessandro Gaietta
@Pratik 显然,在这个例子中有一个Log打印。我想知道如何在JNI调用内使用类似的函数,获取当前时间并将其记录在日志中(我知道如何在JNI内打印日志消息,只是不知道如何获取时间)。 - Alessandro Gaietta
2个回答

16

在移动设备上最好不要使用gettimeofday()currentTimeMillis()。这些函数返回“墙钟时间”,如果网络更新时间,可能会突然向前或向后跳变。

对于性能测量,请改用单调时钟--System.nanoTime() 或带有 CLOCK_MONOTONIC 参数的 clock_gettime()。请注意,此方法返回一个 struct timespec 而不是 struct timeval;主要区别是时钟分辨率为纳秒而不是微秒。

int64_t getTimeNsec() {
    struct timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);
    return (int64_t) now.tv_sec*1000000000LL + now.tv_nsec;
}

除了墙上时钟时间,您可能还对每个线程的 CPU 时间感兴趣。请参见Android 中的线程性能


墙上时钟时间更新的频率是多少?我在gettimeofday()和clock_gettime(CLOCK_PROCESS_CPUTIME_ID)方法之间获得非常不同的时间值。第二个方法似乎更稳定,但它的结果比第一个方法的时间长,而我预期的是更短的时间! - Alessandro Gaietta
1
您可以通过在循环中尽可能快地调用墙钟计时器并在第一次值更改时减去结果来确定更新频率。这个频率因设备和版本而异。PROCESS_CPUTIME时钟只有在进程工作时才会前进;如果它处于睡眠状态,则时钟不会改变。(我建议对于性能工作使用CLOCK_THREAD_CPUTIME_ID,因为它仅在当前线程使用CPU时才会前进。)这些时钟彼此不绑定,并且可能不从零开始。 - fadden
我的意思是,通过使用clock_gettime(CLOCK_PROCESS_CPUTIME_ID)(或THREAD,结果相同)在一小组操作(几毫秒)上进行测量,我得到与gettimeofday()或简单的clock()相等的时间。而在长周期中,我用第一个函数获得了更长的时间,并且用gettimeofday()和clock()获得了相同但更短的时间。注意:在所有情况下,我都测量了终点和起点之间的时间,如果纳秒差异<0(秒++),则clock_gettime() 的结果会进行校正。 clock()除以CLOCKS_PER_SEC进行转换。 - Alessandro Gaietta
进程/线程的 CPU 时间是否包括处理器代表程序执行内核空间指令的时间?还是将其排除在外? - Paschalis

7

在你的C/C++代码中,

#include <sys/time.h>
long long currentTimeInMilliseconds()
{
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return ((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
}

这将为您提供一个结构体,其中包含当前时间的秒数和微秒数,足以轻松地测量两个时间点之间的时间。然后执行转换以返回当前时间(以毫秒为单位)。

编辑:根据@ChrisStratton的建议进行更新。


如果您展示了从结构体转换为64位类型的单个毫秒或微秒值,那么这将是一个更完整的答案... - Chris Stratton
1
我在类型上遇到了一点问题,需要将L添加到数字中,例如: struct timeval stCurrentTime; gettimeofday(&stCurrentTime, nullptr); return ((long long)stCurrentTime.tv_sec * 1000L) + ((long long)stCurrentTime.tv_usec / 1000L); //毫秒 - Gelldur

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