CPU和内存加压工具

 

1. CPU加压工具

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

#define __USE_GNU
#include <sched.h>
#include <pthread.h>

#define INTERVAL 100

/*
**
* gcc -D__USE_GNU -o consume_cpu consume_cpu.c -lpthread
* Usage: ./consume_cpu [<cpu utilization percent>]
**
*/

struct consume_inf{
  int cpu;
  int percent;
};

double get_time(){
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return (tv.tv_sec*1000+tv.tv_usec*1.0/1000);
}

void* consume_thread(void *arg){
  struct consume_inf *inf;
  inf = (struct consume_inf *)arg;
  int cpu = inf->cpu;
  int percent = inf->percent;
  cpu_set_t mask;
  CPU_ZERO(&mask);
  CPU_SET(cpu, &mask);
  if(pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) == -1){
    printf("set affinity failed..");
  }
  
  int busy_span = percent;
  int idle_span = INTERVAL - percent;
  double start_time;
  while(1){
    start_time = get_time();
    while((get_time()-start_time) <= percent);
    usleep(idle_span*1000);
  }
}

int main( int argc, char *argv[]){
  int num = sysconf(_SC_NPROCESSORS_CONF);
  int i = 0;
  pthread_t ptid[1000];
  if(argc < 2){
      printf("usage: %s [<cpu utilization percent>]\n", argv[0]);
      printf("error: cpu utilization percent is a required parameter.\n");
      printf("for example: %s 80\n", argv[0]);
      return(-2);
  }
  int percent = atoi(argv[1]);
  
  struct consume_inf inf[1000];
  for(i = 0; i < num; i++){
    inf[i].cpu = i;
	inf[i].percent = percent;
    if(pthread_create(&ptid[i], NULL, consume_thread, &(inf[i]))){
	  printf("Create pthread (%d) Error.\n", i);
	  return(-1);
	}
  }
  for(i = 0; i < num; i++){
    pthread_join(ptid[i], NULL);
  }
  return(0);
}

Linux下编译方法:

gcc -D__USE_GNU -o consume_cpu consume_cpu.c -lpthread

使用方法:./consume_cpu [<cpu utilization percent>],例如:./consume_cpu 80,CPU整体利用率将保持在80%左右。

2. 内存加压工具

#include <stdio.h>
#include <stdlib.h>
#include <sys/sysinfo.h>
#include <unistd.h>
#include <math.h>
#include <string.h>

#define DEVIATION 100 //允许误差为 DEVIATION 兆
/*
**
* gcc -o consume_mem consume_mem.c
* Usage: ./consume_mem [<ram utilization percent>]
**
*/

typedef struct consume_inf{
  void* memAddr;
  struct consume_inf *next;
}ramlink; //抢占内存链表

void* consume_1M_ram(){
    return malloc(1 << 20);
}

int main( int argc, char *argv[] ){
  if(argc < 2){
      printf("usage: %s [<ram utilization percent>]\n", argv[0]);
      printf("error: ram utilization percent is a required parameter.\n");
      printf("for example: %s 80\n", argv[0]);
      return(-2);
  }
  int percent = atoi(argv[1]);
  int bs_count = 0;
  
  struct sysinfo si;
  sysinfo(&si);
  unsigned long totalram = si.totalram;
  unsigned long targetfree = totalram / 100 * (100 - percent);
  unsigned long nowfree = si.freeram;
  
  ramlink *head = NULL;
  while(1){
    sysinfo(&si);
    nowfree = si.freeram;
    int perc_now = (totalram - nowfree) * 100 / totalram;
    printf("Current ram utilization is %d%%, I am holding %dMB.\n", perc_now, bs_count);
    
    //多吃了内存,释放内存
    if(targetfree > nowfree && (targetfree - nowfree) > DEVIATION * 1024 * 1024 && head != NULL){
      unsigned long tofree_m = (targetfree - nowfree) / 1024 / 1024;
      int j = 0;
      printf("To release %luMB ram...\n", tofree_m);
      for(j = 0; j < tofree_m; j++){
          if(head == NULL){
              printf("All memory(%dMB) has been released.\n", j);
              break;
          }
          ramlink *p = head->next;
          free(head->memAddr);
          free(head);
          head = p;
          bs_count--;
      }
    }
    
    //少吃了内存,继续吃内存
    if(nowfree > targetfree && (nowfree - targetfree) > DEVIATION * 1024 * 1024){
      unsigned long eatram_m = (nowfree - targetfree) / 1024 / 1024;
      int i = 0;
      printf("To preempt %luMB ram...\n", eatram_m);
      for(i = 0; i < eatram_m; i++){
        ramlink *p = (ramlink*)malloc(sizeof(ramlink));
        if(p == NULL) break;
        p->memAddr = consume_1M_ram();
        if(p->memAddr == NULL){
          free(p);
          break;
        }
        memset(p->memAddr, 0, 1 << 20);
        p->next = head;
        head = p;
        bs_count++;
      }
    }
    sleep(10);
  }
  return 0;
}

Linux下编译方法:

gcc -o consume_mem consume_mem.c

使用方法:./consume_mem [<ram utilization percent>],例如:./consume_mem 80,内存利用率将保持在80%左右。

3. 关联实验

将CPU利用率控制为正弦波和锯齿波。

#include <windows.h>
#include <stdlib.h>
#include <math.h>

#define COUNT	200

const double	SPLIT = 0.01;
const double	PI = 3.14159265;
const double	SLOPE = 150;
const int INTERVAL = 300;

DWORD WINAPI SineThread(LPVOID Sine)
{
	DWORD busySpan[COUNT];
	DWORD idleSpan[COUNT];
	int half = INTERVAL/2;
	double radian = 0.0;
	DWORD startTime;
	int i;

	for (i=0; i<COUNT; i++)
	{
		busySpan[i] = (DWORD)(half + half*sin(PI*radian));
		idleSpan[i] = (DWORD)(INTERVAL - busySpan[i]);
		radian += SPLIT;
	}
	i = 0;
	while(1)
	{
		i %= COUNT;
		startTime = GetTickCount();
		while((GetTickCount()-startTime) <= busySpan[i])
			;
		Sleep(idleSpan[i]);
		i++;
	}
	return 0;
}

DWORD WINAPI SawThread(LPVOID Saw)
{
	DWORD busySpan[COUNT];
	DWORD idleSpan[COUNT];
	int half = INTERVAL/2;
	double radian = 0.0;
	DWORD startTime;
	int i;

	for (i=0; i<COUNT; i++)
	{
		busySpan[i] = (DWORD)(SLOPE*radian);
		idleSpan[i] = (DWORD)(INTERVAL - busySpan[i]);
		radian += SPLIT;
	}
	i = 0;
	while(1)
	{
		i %= COUNT;
		startTime = GetTickCount();
		while((GetTickCount()-startTime) <= busySpan[i])
			;
		Sleep(idleSpan[i]);
		i++;
	}
	return 0;
}

int main()
{
	HANDLE hThread1, hThread2;
	DWORD dwThreadId1, dwThreadId2;

	hThread1 = CreateThread(NULL, 0, SineThread, 0, CREATE_SUSPENDED, &dwThreadId1);
	hThread2 = CreateThread(NULL, 0, SawThread, 0, CREATE_SUSPENDED, &dwThreadId2);
	SetThreadAffinityMask(hThread1, 1);
	SetThreadAffinityMask(hThread2, 2);
	ResumeThread(hThread1);
	ResumeThread(hThread2);
	SuspendThread(GetCurrentThread());
	return 0;
}

CPU-1.png