Я использую крючки модуля безопасности Linux, чтобы добавить некоторые пользовательские функции для системного вызова recv(). Я хочу измерить накладные расходы этой функции по сравнению с нетронутой recv(). Я написал простой сервер tcp, который я запускаю с моим модулем и без него. Этот tcp-сервер вызывает функцию recv() "N" количество раз. Он измеряет время, затраченное на каждый recv, с чем-то вроде:
clock_gettime(before);
recv()
clock_gettime(after);
global_time += after - before.
В конце я печатаю среднее время для одного recv() с "global_time/N". Позволяет называть это время как "user_space_avg_recv".
Внутри моего модуля я хочу поместить функции измерения времени, чтобы вычислить точное время выполнения моего крючка. Я попробовал 3 метода.
-
Я использовал jiffies следующим образом:
sj = jiffies; my_hook(); ej = jiffies; current->total_oh = ej - sj;
Но я вижу, что нет никакой разницы между значениями sj и ej. Следовательно, total_oh не изменяется.
-
Я использовал current_kernel_time(), так как я думал, что он возвращает время в наносекундах. Однако, опять же, не было никакой разницы в до и после времени.
-
Я использовал get_cycles. Я печатаю полные циклы, когда процесс завершается. Однако, когда я конвертирую эти общие значения циклов в миллисекунды, он выходит намного больше, чем "user_space_avg_recv". Это не имеет смысла, поскольку измеренное значение внутри ядра всегда будет меньше значения времени, измеренного от пользовательского пространства. Это может означать, что я либо не измеряю, используя правильный API, либо делаю ошибку при преобразовании значения из циклов в миллисекунды.
Я использую следующую формулу для преобразования циклов в миллисекунды:
avg overhead of my hook in milliseconds =
(((cycles / 2.99) / 10^6) / N)
2,99, потому что моя тактовая частота 2,99 ГГц
Некоторые моменты:
-
Моя программа пространства пользователя привязана к одному ядру с использованием сродства с привязкой.
-
Я использую ядро 2.6.22.14
-
Чтобы отключить ядро от переключения контекстов во внутреннем ящике, я использую preempt_disable() и preempt_enable(). Таким образом, он не будет считать время выполнения других потоков ядра. Даже тогда, так как мой крючок использует некоторые операции ввода-вывода, мой поток может освободить элемент управления, или может произойти прерывание, которое может увеличить общее количество циклов.
Вопрос: Как я могу точно измерить время выполнения функции внутри ядра?