编程之美第一道题目就是如何让CPU使用率曲线成为一条正弦曲线,本文在Linux下实现这个效果。
程序运行时间
一个进程的运行时间大致分为user time,kernel time和waiting time
- int main()
- {
- int i;
- for(i = 0; i < 100000000; i ++) //用户空间执行
- getpid(); //系统调用,内核空间执行
- //scanf和printf是C标准库里的,还要调用Linux的系统调用read和write
- scanf("%d\n",&i);
- printf("%d\n",i);
- return 0;
- }
- while(1)
- {
- for(i = 0; i < 100000; i ++); //CPU忙,占用的时间是user time
- usleep(10000); //CPU闲,属于waiting time
- }
- int main()
- {
- int i;
- while(1)
- {
- for(i = 0; i < n; i++);
- usleep(m);
- }
- return 0;
- }
- .L2:
- movl $0, -8(%ebp)
- jmp .L3
- .L4:
- addl $1, -8(%ebp)
- .L3:
- cmpl $3999999, -8(%ebp)
- jle .L4
- movl $60000, (%esp)
- call usleep
- jmp .L2
注:上面说一个时钟周期执行一条指令是不合适的,各种指令的执行时间不同。计算机里的周期主要有时钟周期,机器周期,指令周期。一条指令的周期称为指令周期,由几个机器周期做成,而一个机器组成由几个时钟周期组成。上面的三条指令都需要取内存,因此时间长。如果把循环变量放在寄存器里,那么用的时间要小的多:
将内存数-8(%ebp)改为寄存器数%ebx
- .L2:
- movl $0, %ebx
- jmp .L3
- .L4:
- addl $1, %ebx
- .L3:
- cmpl $13199999, %ebx
- jle .L4
- movl $60000, (%esp)
- call usleep
- jmp .L2
- //伪代码
- int main()
- {
- int start_time, current_time;
- while(1)
- {
- start_time = GetCurrentTime();
- current_time = start_time;
- while(current_time - start_time < 60)
- current_time = GetCurrentTime();
- sleep(60);
- }
- }
- #include <stdio.h>
- #include <stdlib.h>
- int main()
- {
- struct timeval tv;
- long long start_time,end_time;
- while(1)
- {
- gettimeofday(&tv,NULL);
- start_time = tv.tv_sec*1000000 + tv.tv_usec;
- end_time = start_time;
- while((end_time - start_time) < 60000)
- {
- gettimeofday(&tv,NULL);
- end_time = tv.tv_sec*1000000 + tv.tv_usec;
- }
- usleep(60000);
- }
- return 0;
- }
现在我们用这种方法实现CPU使用率的正弦曲线。
首先要确定这个曲线的函数。这个函数的最大值是1,最小值是0,因此肯定是0.5(sin(tx) + 1)。
怎么确定t呢?
我们可以认为,曲线的更新周期应该大于100ms,我们以100ms为单位,把100ms的平均使用率作为这100ms末的使用率。
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- int main()
- {
- struct timeval tv;
- long long start_time,end_time;
- long long busy_time[100];
- long long idle_time[100];
- int i;
- for(i = 0; i < 100; i++)
- {
- busy_time[i] = 100000 * 0.5 * (sin(i*0.0628) + 1);
- idle_time[i] = 100000 - busy_time[i];
- }
- i = 0;
- while(1)
- {
- gettimeofday(&tv,NULL);
- start_time = tv.tv_sec*1000000 + tv.tv_usec;
- end_time = start_time;
- while((end_time - start_time) < busy_time[i])
- {
- gettimeofday(&tv,NULL);
- end_time = tv.tv_sec*1000000 + tv.tv_usec;
- }
- usleep(idle_time[i]);
- i = (i+1)%100;
- }
- return 0;
- }
本文出自 “牛哥的博客” 博客,转载请与作者联系!