Yanyg - Software Engineer

面试 - 如何让应用程序CPU使用率50%

目录

在分析二叉树最大距离问题时,搜索购买了《编程之美》,该书最前面谈到实现一个应用占用CPU 50%问题。

1 我的解答

使用rdtsc/gettimeofday查询时间,并控制休眠和cpu占用百分比,最终达成目的。添加 adjust微调循环体本身的CPU占用,实际测试观察意义不大。多核下设置affinity绑定CPU,可以提高稳定性,示例代码未添加。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

union rdtsc_union {
        unsigned long v64;
        struct {
                unsigned int low32;
                unsigned int high32;
        };
};

static __always_inline unsigned long rdtsc_ordered(void)
{
        union rdtsc_union ru;

        asm volatile("mfence\n\tlfence\n\t" ::: "memory");
        asm volatile("rdtsc" : "=a" (ru.low32), "=d" (ru.high32));

        return ru.v64;
}

int main(int argc, char *argv[argc])
{
        int ratio = 50, idx;
        unsigned long rs, interval, interval_10ms, adjust;
        volatile int op_dummy = 0;

        if (argc > 1)
                ratio = atoi(argv[1]);

        if (ratio < 0 || ratio > 100) {
                fprintf(stderr, "invalid ratio(%d), reset to 50\n", ratio);
                ratio = 50;
        }

        // benchmark
        rs = rdtsc_ordered();
        usleep(1000*10); // 10 millseconds
        interval_10ms = rdtsc_ordered() - rs;

        // optional adjust result for precising
        rs = rdtsc_ordered();
        for (idx = 0; idx < 100; ++idx) {
                interval = rdtsc_ordered() - rs;
                if (idx > ratio) {
                        struct timeval tv;
                        gettimeofday(&tv, NULL); // fake syscall
                        rdtsc_ordered();
                }
        }
        // // 100 for os syscall, so call time
        adjust = (rdtsc_ordered() - rs)*10000*1000/interval_10ms/ratio;

        printf("interval_10ms=%lu, adjust=%lu, press Ctrl+c exit\n", interval_10ms, adjust);

        while (1) {
                interval = rdtsc_ordered() - rs;
                if (interval < interval_10ms*ratio) {
                        ++op_dummy;
                } else {
                        usleep(1000*10*(100-ratio) + adjust);
                        rs = rdtsc_ordered();
                }
        }

        return  0;
}

GCC编译gcc -Wall -o cpuratio cpuratio.c测试,基本CPU占用在49.5%~50.5%之间。传递参数设置不同占用比:

yanyg@t440:~/org/h/code$ gcc cpu-ratio.c -Wall -o cpu-ratio
yanyg@t440:~/org/h/code$ ./a.out
interval_10ms=29143618, adjust=228, press Ctrl+c exit
^C
yanyg@t440:~$ top
  top output capture:
  12023 yanyg     20   0    4172    652    576 S  50.2  0.0   0:03.02 cpu-ratio

yanyg@t440:~/org/h/code$ ./cpu-ratio 80
interval_10ms=29217598, adjust=262, press Ctrl+c exit
^C
yanyg@t440:~$ top
  top output capture:
  12059 yanyg     20   0    4172    740    664 R  80.1  0.0   0:12.41 cpu-ratio

2 References

编程之美 - CPU曲线
http://tianshu.xyz/blog/108/