2011-01-07 114 views
8

我正在研究SDIO UART Linux/Android驱动程序的性能基准测试,并在要分析的读取,写入函数实现的开始和结束时使用current_kernel_time(),然后打印时间差。current_kernel_time()有多可靠?

大部分时间我得到的时间差为0(零)毫微秒(不管读取/写入数据的大小:16-2048字节),这在逻辑上我认为是不正确的,只有很少几次我得到一些希望这些值是正确的。

current_kernel_time()有多可靠?

为什么我大部分时间都得到0ns?

我打算在内核级别来分析,以获得更多details..before可有人扔一些轻这个behavior..has有人观察到这样的事以前......

此外,任何建议,以帮助/更正我的基准测试方法也很受欢迎!

谢谢。编辑:
这是从Linux内核版本2.6.32.9读取的代码。我添加current_kernel_time(),如下下的#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 

} 
+0

为什么你不显示一些代码?很难分辨你看不到的东西有什么问题。 – 2011-01-07 16:12:59

+0

什么平台?这种类型的问题非常硬件特定(或至少是特定于架构的) – 2011-01-07 17:11:57

回答

10

current_kernel_time是指用于计时,而不是性能测量。 它返回的值不是基于实际的计时器,而是基于由定时器中断更新的时间值。所以精度取决于定时器中断周期。 ,你会得到较差的分辨率。

但是,也许getnstimeofday,更适合您的需要,因为它也读取实际的时钟源来调整时间值。它应该更加细致。

基于内核source,可能最好的功能是getrawmonotonic,在极少数情况下,系统时间在测量期间向后调整。