current_kernel_time() 的可靠性如何?
我正在研究 SDIO UART Linux/Android 驱动程序的性能基准测试,并在待分析的读取、写入函数实现的开始和结束时使用 current_kernel_time() ,然后打印时间差。
大多数时候,我得到的时间差为 0(零)纳秒(无论要读/写的数据大小:16-2048 字节),这在逻辑上我认为是不正确的,只有极少数情况下我得到一些值,希望这些是正确的。
current_kernel_time() 的可靠性如何?
为什么我大多数时候得到 0ns?
我计划在内核级别进行分析以获取更多详细信息..在此之前有人可以对这种行为进行一些说明..之前是否有人观察到类似的事情...
此外,任何帮助/纠正我的基准测试方法的建议也是欢迎!
谢谢。
编辑:
这是从Linux内核版本2.6.32.9读取的代码。我在 #ifdef-endif 下添加了 current_kernel_time() ,如下所示:
static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status)
{
#ifdef SDIO_UART_DEBUG
struct timespec time_spec1, time_spec2;
time_spec1 = current_kernel_time();
#endif
struct tty_struct *tty = port->tty;
unsigned int ch, flag;
int max_count = 256;
do {
ch = sdio_in(port, UART_RX);
flag = TTY_NORMAL;
port->icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
UART_LSR_FE | UART_LSR_OE))) {
/*
* For statistics only
*/
if (*status & UART_LSR_BI) {
*status &= ~(UART_LSR_FE | UART_LSR_PE);
port->icount.brk++;
} else if (*status & UART_LSR_PE)
port->icount.parity++;
else if (*status & UART_LSR_FE)
port->icount.frame++;
if (*status & UART_LSR_OE)
port->icount.overrun++;
/*
* Mask off conditions which should be ignored.
*/
*status &= port->read_status_mask;
if (*status & UART_LSR_BI) {
flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
flag = TTY_FRAME;
}
if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
tty_insert_flip_char(tty, ch, flag);
/*
* Overrun is special. Since it's reported immediately,
* it doesn't affect the current character.
*/
if (*status & ~port->ignore_status_mask & UART_LSR_OE)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
*status = sdio_in(port, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
tty_flip_buffer_push(tty);
#ifdef SDIO_UART_DEBUG
time_spec2 = current_kernel_time();
printk(KERN_INFO "\n MY_DBG : read took: %ld nanoseconds",
(time_spec2.tv_sec - time_spec1.tv_sec) * 1000000000 + (time_spec2.tv_nsec - time_spec1.tv_nsec));
#endif
}
I am working on performance benchmarking of a SDIO UART Linux/Android driver and used current_kernel_time() at start and end of the to-be-analysed read, write function implementation, then printing the time difference.
Most of the time I get time difference as 0 (zero) nanoseconds (irrespective of size of the data to read/write : 16-2048 bytes) which logically I think is incorrect, only a very few times I get some values hopefully those are correct.
How reliable is the current_kernel_time()?
Why I get 0ns most of the times?
I am planning to profile at kernel level to get more details..before that can somebody throw some light on this behavior..has anybody observed anything like this before...
Also, any suggestions to help/correct my approach to benchmarking are also welcome!
Thank you.
EDIT:
This is the read code from Linux kernel version 2.6.32.9. I added current_kernel_time() as below under #ifdef-endif:
static void sdio_uart_receive_chars(struct sdio_uart_port *port, unsigned int *status)
{
#ifdef SDIO_UART_DEBUG
struct timespec time_spec1, time_spec2;
time_spec1 = current_kernel_time();
#endif
struct tty_struct *tty = port->tty;
unsigned int ch, flag;
int max_count = 256;
do {
ch = sdio_in(port, UART_RX);
flag = TTY_NORMAL;
port->icount.rx++;
if (unlikely(*status & (UART_LSR_BI | UART_LSR_PE |
UART_LSR_FE | UART_LSR_OE))) {
/*
* For statistics only
*/
if (*status & UART_LSR_BI) {
*status &= ~(UART_LSR_FE | UART_LSR_PE);
port->icount.brk++;
} else if (*status & UART_LSR_PE)
port->icount.parity++;
else if (*status & UART_LSR_FE)
port->icount.frame++;
if (*status & UART_LSR_OE)
port->icount.overrun++;
/*
* Mask off conditions which should be ignored.
*/
*status &= port->read_status_mask;
if (*status & UART_LSR_BI) {
flag = TTY_BREAK;
} else if (*status & UART_LSR_PE)
flag = TTY_PARITY;
else if (*status & UART_LSR_FE)
flag = TTY_FRAME;
}
if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
tty_insert_flip_char(tty, ch, flag);
/*
* Overrun is special. Since it's reported immediately,
* it doesn't affect the current character.
*/
if (*status & ~port->ignore_status_mask & UART_LSR_OE)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
*status = sdio_in(port, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
tty_flip_buffer_push(tty);
#ifdef SDIO_UART_DEBUG
time_spec2 = current_kernel_time();
printk(KERN_INFO "\n MY_DBG : read took: %ld nanoseconds",
(time_spec2.tv_sec - time_spec1.tv_sec) * 1000000000 + (time_spec2.tv_nsec - time_spec1.tv_nsec));
#endif
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
current_kernel_time 用于计时,而不是用于性能测量。
它返回一个值,不是基于实际计时器,而是基于由计时器中断更新的时间值。所以精度取决于定时器中断周期。
并且你的分辨率很差。
然而,也许
getnstimeofday
更适合您的需要,因为它还读取实际的时钟源来调整时间值。它应该更细粒度。基于内核源,也许是最好的函数是
getrawmonotonic
,以防万一在测量过程中系统时间向后调整。current_kernel_time is meant for timekeeping, not for performance measurement.
It returns, a value, not based on an actual timer, but on a time value that is updated by a timer interrupt. So the precision depends on the timer interrupt period.
and you get poor resolution.
However, perhaps
getnstimeofday
, is more suited to your need, since it also read the actual clock source to adjust the time value. It should be more fine grained.Based on kernel source, maybe the best function is
getrawmonotonic
, in the unlikely event that the system time is adjusted backward during your measurement.