единственный syscsll в линукс, возвращающий время -
это gettimeofday(), все остальные обертки в libc или
кернел. clock_gettime() немного другое, но все равно.
/dev/rtc вообще не причем.
можно использовать rdtsc для получения значения
регистра процессора, где хранится число тиков с
момента включения, это будет быстрее. но в случае
smp можно нарваться на не синхронизированные
процессоры.
> clock_gettime() немного другое, но все равно.
Вроде как разрешение у clock_gettime() лучше? Всё равно - это потому что из user-space?
В дополнение: кроме do_gettimeofday() в kernel-space есть варианты получения точного времени (в нс)?
> Вроде как разрешение у clock_gettime() лучше?
теоретически. но мы же о Linux говорим?
kernel/posix-timers.c:
#define CLOCK_REALTIME_RES TICK_NSEC
потом, ему же достаточно 1мс.
главное, быстрее работать не будет. и вообще
kernel/posix-timers.c:do_posix_gettime():
if (clock->clock_get)
return clock->clock_get(tp);
do_gettimeofday(&tv);
clock_get только для CLOCK_MONOTONIC.
> Всё равно - это потому что из user-space?
это я не понял.
> кроме do_gettimeofday() в kernel-space есть варианты
> получения точного времени (в нс)?
переносимого нет. есть sched_clock(), он в нанах, но
ненадежен, для него это неважно. и вообще годится только
для измерения разницы времени, а не времени.
> А по подробнее можна???
о чем?
вообще, непонятно как это gettimeofday слишком
медленна. очень редко возникают ситуации, когда
ее нужно вызывать часто.
>вообще, непонятно как это gettimeofday слишком
медленна. очень редко возникают ситуации, когда
ее нужно вызывать часто.
например мне нужно в цикле измерить время выполнения некоторой ф-и которое составляет ~10мс.
время выполнения gettimeofday составляет ещё около 10 секунд итого прога начинает работать в три раза медленее что многовато
> например мне нужно в цикле измерить время выполнения
> некоторой ф-и которое составляет ~10мс. время выполнения
> gettimeofday составляет ещё около 10 секунд итого прога
> начинает работать в три раза медленее что многовато
конечно, делать profile с помощью gettimeofday() вообще
странно. тогда rdtsc. только непонятно, зачем вообще
эти измерения, кроме как для отладки. но надо - так
надо, я не спорю.
>> Вроде как разрешение у clock_gettime() лучше?
>теоретически. но мы же о Linux говорим?
Меня сам факт появления в ядре более точной функции времени заинтересовал. То есть вроде как есть возможность в дальнейшем довести её до ума.
POSIX 1003.1 описывает реализацию как для CLOCK_REALTIME так и для CLOCK_MONOTONIC. А сейчас clock_gettime() работает через do_gettimeofday() и _пока_ реализована только для CLOCK_MONOTONIC, так?
>конечно, делать profile с помощью gettimeofday() вообще
странно. тогда rdtsc. только непонятно, зачем вообще
эти измерения, кроме как для отладки. но надо - так
надо, я не спорю.
если бы я знал чтото другое то возможно б заюзал.
А как юзать rdtsc??? ато man о rdtsc ничего не знает
> А сейчас clock_gettime() работает через do_gettimeofday()
> и _пока_ реализована только для CLOCK_MONOTONIC, так?
нет, ну сами на код посмотрите. все они пока
используют do_gettimeofday(). CLOCK_MONOTONIC
еще не позволяет получить два одинаковых ответа.
/*
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define rdtsc(dest) \
__asm__ __volatile__("nop; mfc0 %0,$9; nop" : "=r" (dest))
int main(int argc, char **argv)
{
unsigned int count1,count2,count3,fix;
printf("rdtsc demo (using mfc0 on mips)\n");
rdtsc(count1);
rdtsc(count2);
fix = count2-count1;
rdtsc(count1);
printf("rdtsc() took %5ui cycles\n",fix);
rdtsc(count2);
printf("printf() took %5ui cycles\n",count2-count1-fix);
rdtsc(count1);
sleep(0);
rdtsc(count2);
printf("sleep(0) took %5ui cycles\n",count1-count1-fix);
rdtsc(count1);
sleep(1);
rdtsc(count2);
printf("sleep(1) took %5ui cycles\n",count1-count1-fix);
return 0;
}
/*
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
*/
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#include <linux/module.h>
#include <linux/errno.h>
#define rdtsc(dest) \
__asm__ __volatile__("nop; mfc0 %0,$9; nop" : "=r" (dest))
int i;
int init_module()
{
unsigned int count1,count2,fix;
rdtsc(count1);
rdtsc(count2);
fix = count2-count1;
rdtsc(count1);
printk("rdtsc() took %5u cycles\n",fix);
rdtsc(count2);
printk("printk() took %5u cycles\n",count2-count1-fix);
return 0;
}