当前位置: 首页>编程语言>正文

zabbix cpu使用率看哪个 笔记本看cpu使用率

本题来自《编程之美》

  • 操作系统:Mac OS X 10.15.3
  • 硬件信息3.1GHz i5四核处理器
  • 代码使用C语言

问题描述

1. CPU的占用率固定在50%,是一条直线;
2. CPU的具体占用率由命令行参数决定(参数范围1~100);
3. CPU占用率的状态是一个正弦曲线。

基础知识

MacOS系统下,「活动监视器」可以查看进程、处理器核数,也可以在「终端」输入top查看任务进程及其详细信息。




zabbix cpu使用率看哪个 笔记本看cpu使用率,zabbix cpu使用率看哪个 笔记本看cpu使用率_GAP,第1张


Mac OS X活动监视器

CPU占用率 = CPU执行应用程序的时间:刷新周期总时间。

某个进程的CPU使用率就是这个进程在一段时间内占用的CPU时间占总的CPU时间的百分比。比如某个开启多线程的进程1s内占用了CPU0 0.6s, CPU1 0.9s, 那么它的占用率是150%。

时间片(timeslice)又称为“量子(quantum)”或” 处理器片(processor slice)”是分时操作系统分配给每个正在运行的进程微观上的一段CPU时间。

问题 1. 占用率固定为50%

无限循环情况下:


int main(){
    while (1){
        ;
    }
}


书中的例子应该是单核处理器,一个无限循环可以让CPU占用率几乎达到100%;但是实际操作后,我的电脑占用率总体是一条25%-30%的直线——这是因为处理器是多核的。

可以通过多线程编程来提高CPU占用率。

多线程编程(Multithreading Programming)

Mac OS是POSIX系统,用pthread创建两个线程就可以让CPU占用率达到50%

简单代码如下:(更多多线程函数介绍详见 (C语言多线程编程-线程的基本函数_c/c++_shuaixio的博客))


#include <pthread.h>
#include <stdio.h>
void
dead_loop(void)
{
    while (1){
        ;
    }
}

int
main(void)
{
    pthread_t thread[2];  
    for (int i=0;i<2;i++) pthread_create(&thread[i], NULL, dead_loop, NULL);  //创建两个线程
    pthread_join(thread[0], NULL); //等待第一个线程结束(永远也不会结束)
    printf("Program Ends.");
}


之后编译程序


$ gcc -lpthread program_name.c


结果达成要求——CPU占用率大约为50%,直线的波动是截图和其他系统活动造成的干扰。

问题2. 自定义CPU占用率

OS X 不支持GetTickCount() , Sleep(), 解决方法如下:

用time.h头文件内的函数clock()得到当前CPU clock ticks的次数作差后除以CLOCKS_PER_SEC 就可以得到CPU时间:


while ((clock()-start)/CLOCKS_PER_SEC*1000<busy_time){
/* code */
}


另外要注意Sleep()的单位是ms,sleep()的单位是s;前者仍然是Windows特有函数,在Mac上不能使用。我在Stack Overflow上发现了一段sleep_ms()函数代码,适用于Windows、老版POSIX和新版POSIX(新版不再支持usleep()函数):


#ifdef WIN32
#include <windows.h>
#elif _POSIX_C_SOURCE >= 199309L
#include <time.h>   // for nanosleep
#else
#include <unistd.h> // for usleep
#endif

void sleep_ms(int milliseconds) // cross-platform sleep function
{
#ifdef WIN32
    Sleep(milliseconds);
#elif _POSIX_C_SOURCE >= 199309L
    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
    nanosleep(&ts, NULL);
#else
    usleep(milliseconds * 1000);
#endif
}


题目代码:


#include<stdio.h>
#include<pthread.h>
#include<time.h>

int busy_time, idle_time; //定义全局变量

void dead_loop(void);
void sleep_ms(long milliseconds);

int main(){
    float percent; 
    printf("Enter the target percentage (in float, e.g. 0.7): "); 
    scanf("%f",&percent); // 读入目标CPU占用率
    /* 确定时间参数 */
    int total_time = 500; //经过大致试验得出的比较合适的值
    busy_time = (int)total_time*percent;
    idle_time = total_time-busy_time;
    /*创建多线程*/
    pthread_t thread[3];
    for (int i=0;i<3;i++) pthread_create(&thread[i],NULL,dead_loop,NULL);
    dead_loop();  //程序一共有4个线程
    pthread_join(thread[0], NULL);
    return 1; 
}
void sleep_ms(long milliseconds){
    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
    nanosleep(&ts, NULL);
}
void dead_loop(void){
    static __thread clock_t start; // 创建线程内记录CPU时间的局部变量
    while (1){
        start = clock(); 
        while ((clock()-start)/CLOCKS_PER_SEC*1000<busy_time){
            ;
        }
        sleep_ms(idle_time);
    }
}


结果

0.5以上的参数得出的结果还是比较准确的,但是0.5以下的参数就不那么准确了(因为我是新手+比较菜,并且时间有限,目前无法解决这个问题)——分析出原因是

  1. 程序频繁sleep、awake所以系统内核调度程序会产生比较大的干扰。
  2. 自定义了一些函数,比如sleep_ms()。

问题3. CPU占用率的状态是一个正弦曲线。

我选择的正弦曲线 y=0.25sin(x)+0.75

大概思路是对一整个周期的正弦曲线采样(代码示例里采样25个点),计算出对应的busy_time,idle_time。


#include<stdio.h>
#include<pthread.h>
#include<time.h>
#include<math.h>
#define GAP 25 //正弦曲线每周期样本点的个数
int busy_time[GAP], idle_time[GAP]; //定义全局变量

void dead_loop(void);
void sleep_ms(long milliseconds);

int main(){
    int i; 
    /* 确定时间参数 */
    int total_time = 500; 
    float percent[GAP];
    for (i=0;i<GAP;i++){
        percent[i] = 0.25*sin(0.5*i)+0.75;
        busy_time[i] = total_time*percent[i];
        idle_time[i] = busy_time[i]-percent[i];
    }
    /*创建多线程*/
    pthread_t thread[3];
    for (i=0;i<3;i++) pthread_create(&thread[i],NULL,dead_loop,NULL);
    dead_loop();  //程序一共有4个线程
    pthread_join(thread[0], NULL);
    return 1; 
}
void sleep_ms(long milliseconds){
    struct timespec ts;
    ts.tv_sec = milliseconds / 1000;
    ts.tv_nsec = (milliseconds % 1000) * 1000000;
    nanosleep(&ts, NULL);
}
void dead_loop(void){
    static __thread clock_t start; // 创建线程内记录CPU时间的局部变量
    while (1){
        for (int j=0;j<GAP;j++){
            for (int k=0;k<10;k++){  //让正弦曲线的周期变长
                start = clock(); 
                while ((clock()-start)/CLOCKS_PER_SEC*1000<busy_time[j]){
                    ;
                }
                sleep_ms(idle_time[j]);
            }
        }
    }
}


结果:总体来说是平滑的sin曲线(User曲线的波动仍然是因为其他应用的干扰)


zabbix cpu使用率看哪个 笔记本看cpu使用率,zabbix cpu使用率看哪个 笔记本看cpu使用率_#include_02,第2张



参考资料

理论基础

时间片-乌龟运维-51CTO博客

CPU使用率原理及计算方式 - gatsby123

多线程编程相关

Multithreading in C

Basics of multithreading in C

linux编程 - C/C++每线程(thread-local)变量的使用 (参考了第一小节)

C library function - clock()

Sleep()函数在Mac上的替代


https://www.xamrdz.com/lan/5y31957292.html

相关文章: