LINUX:ITIMER_PROF 的分辨率/粒度是多少?

标签 linux ubuntu timer system-calls

问题:
LINUX 配置文件计时器的分辨率是多少?显然,这是特定于系统的,因此我将在下面提供更多详细信息。
背景:
我正在尝试使用 Google GPerfTools 套件,但我发现无论我多么努力,我都无法获得超过 200 个样本/秒的 CPU 时间(不是挂钟时间,甚至更低),即使允许的最大值在 GPerfTools 中是 4000/秒。
Please see this (unloved) question: /questions/22799490
通过查看 GPerfTools 代码,我还发现它使用的是 ITIMER_PROF (这并不奇怪),并且正在使用 setitimer(2)具有正确 timestruct 值的系统调用(duh!):

void ProfileHandler::StartTimer() {
  if (!allowed_) {
    return;
  }
  struct itimerval timer;
  timer.it_interval.tv_sec = 0;
  timer.it_interval.tv_usec = 1000000 / frequency_;
  timer.it_value = timer.it_interval;
  setitimer(timer_type_, &timer, 0);
}
因此,采样率的限制要么是系统 ITIMER_PROF 限制,要么是 GPerfTools 如何与我正在分析的程序交互的副产品(也许当我们在 I/O 上被阻塞时计时器正在关闭?当这种情况发生时。 ..也许这不算作样本?:))
系统规范:
我在运行 Ubuntu Linux 的标准 x86_64 机器上运行。这是我的 uname 结果:Linux <hostname> 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 17:37:58 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux程序和 GPerfTools 库是在 32 位模式下编译的。事实上,configure GPerfTools 构建中的步骤是在 32 位 chroot'd 中完成的 jail setarch'd到i386。

最佳答案

在不同的 Ubuntu x86 LINUX 机器(包括 x86 虚拟机)上进行的重复测试均确认 250/秒,或实际使用 CPU 时的 4ms 间隔。在这个时代,这真的是正确的吗?测试程序包括在下面

示例结果:

./itimer 200 3
freq = 200
timeout = 3
When over, you should see 599 firings
PERF timer fired 599 times
VIRTUAL timer fired 599 times

./itimer 500 3
freq = 500
timeout = 3
When over, you should see 1499 firings
PERF timer fired 749 times
VIRTUAL timer fired 749 times

测试程序
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>

struct itimerval mrVal;
struct itimerval timeout;

int ncalls = 0;
int nvcalls = 0;
void killer(int signum)
{
    // Off by a few because we don't stop the timers,
    // but good enough for testing purposes
    printf("PERF timer fired %d times\n", ncalls);
    printf("VIRTUAL timer fired %d times\n", nvcalls);
    exit(0);
}

void interval_handler(int signum)
{
    ncalls += 1;
}

void virtual_handler(int signum)
{
    nvcalls += 1;
}

static double keeper = 12.345;

int main(int argc, char **argv)
{
    if (argc < 3) {
        printf("Usage: itimer freq seconds-to-run\n");
        exit(1);
    }
    int freq = atoi(argv[1]);
    int sleepsex = atoi(argv[2]);
    printf("freq = %d\n", freq);
    printf("timeout = %d\n", sleepsex);
    printf("When over, you should see %d firings\n",
                    (freq * sleepsex) - 1);

    timeout.it_interval.tv_sec = sleepsex;
    timeout.it_interval.tv_usec = 0;
    timeout.it_value = timeout.it_interval;

    mrVal.it_interval.tv_sec = 0;
    mrVal.it_interval.tv_usec = 1000000 / freq;
    mrVal.it_value = mrVal.it_interval;
    if(signal(SIGPROF, interval_handler) == SIG_ERR) {
        printf("HOSER!\n");
    }
    if(signal(SIGVTALRM, virtual_handler) == SIG_ERR) {
        printf("HOSER!\n");
    }
    if(signal(SIGALRM, killer) == SIG_ERR) {
        printf("HOSER!\n");
    }
    if(signal(SIGINT, killer) == SIG_ERR) {
        printf("HOSER!\n");
    }
    setitimer(ITIMER_PROF, &mrVal, 0);
    setitimer(ITIMER_VIRTUAL, &mrVal, 0);
#if 1
    // Use CPU. Otherwise, the PERF timer doesn't go off
    // Trivial floating point stuff that counts good enough
    // as work
    setitimer(ITIMER_REAL, &timeout, 0);
    while(1) {
        double d = keeper;
        d/=1.3773;
        d*=1.3777;
        keeper = d;
    }
#else
    sleep(sleepsex);
    killer(0);
#endif
}

关于LINUX:ITIMER_PROF 的分辨率/粒度是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22848764/

相关文章:

Gitlab无法在服务器上克隆,但可以在客户端克隆

Android模拟器在启动时卡住

jquery - 如何在jquery中使用不同的值多次调用函数

c# - 从 BackgroundWorker 启动时计时器是否工作?

linux - 在 UNIX 中运行脚本的 Crontab

c - 查看是否通过 tcp 传递了消息

linux - 在没有互联网访问的情况下安装 unix 程序

linux - 如何从文件中每一行的字符串中选择第 n 个字符?

Ubuntu + Vagrant + docker compose 不使用 Virtualbox

java - 在Java中,如何每X秒执行一次代码?