windows下测试硬盘的读写性能(这是模拟我们公司业务对硬盘读写速度的测试)

/***********************************************************************************
注意:这个代码是根据我们公司具体情况来写的,测试我们公司业务数据的读写性能(看看有多少数据的读写时间我们不能接受)的。可能与你的实际情况不相符合。
1 该代码仅仅考虑读写速度,不考虑线程间的同步之类的
2 该代码是模拟根据业务数据读写的大小来进行写的,跟具体的读写文件大小有关。
3该代码最终形成的结果值是一个二维表,里面统计了,读写不同字节范围花的时间段的统计。
要点:1预先创建若干个固定大小的文件
        2对于每个文件,创建一个线程去写它,写是随机写的,但不能把文件写大
        3读线程随机读取已经存在的文件,读取位置也是随机写的。
        4对于随机读取的大小也是一定范围内的随机数(这里实际上可以用boost生成正态分布的随机数更好,CSDN上有现成代码)。
**********************************************************************************/
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include "windows.h"
#include <time.h>
#include <assert.h>
#include <math.h>
#include <fcntl.h>

//二维数组的单维数
#define ARRAY_SIZE 20
#define MAX_THREAD      1024


//全局数据区
/**************************************************************
以下二维表是我们最终要得到的结果表值。
read_time_table,write_time_table数组结构如下:
size(Byte)\time(mic) [0,10) [10,20) [20,40) [40,80) [80,160) .....
[0,32) 0 0 0 0 0 ...
[32,64) 0 0 0 0 0 ...
[64,128) 0 0 0 0 0 ...
[128,256) 0 0 0 0 0 ...
[256,512) 0 0 0 0 0 ...
...... ... ... ... ... ... ...
***************************************************************/
DWORD  read_time_table[ARRAY_SIZE][ARRAY_SIZE];
DWORD  write_time_table[ARRAY_SIZE][ARRAY_SIZE];
//读写数据的缓冲区
char buffer[10240];

//写线程参数结构体声明
typedef struct _THREAD_WRITE_PARAM
{
    int i; //第几个线程
DWORD file_size;
DWORD write_range;
char* dir;
} THREAD_WRITE_PARAM, *LPTHREAD_WRITE_PARAM;

//读线程参数结构体声明
typedef struct _THREAD_READ_PARAM
{
    int sum_files;//可供读的文件总数
DWORD file_size;
DWORD read_range;
char* dir;
} THREAD_READ_PARAM, *LPTHREAD_READ_PARAM;

//打印结果线程参数结构体声明
typedef struct _THREAD_RECODE_PARAM
{
char* dir;
char* name;
DWORD time;//每隔多长时间(毫秒)打印一次结果
}THREAD_RECODE_PARAM, *LPTHREAD_RECODE_PARAM;

//函数声明
HANDLE Open_File(char*);
int Close_File(HANDLE);
DWORD CreateRandom(int, int);
int StoreTable(char*, char*, DWORD);
DWORD WINAPI GetTimeTable(LPVOID);
int RecodeTime(int, DWORD, double);
DWORD WINAPI Write_thread(LPVOID);
DWORD WINAPI Read_thread(LPVOID);
int CreateFile(char*, char*, int);
HANDLE Open_File(char*);
int Close_File(HANDLE);
int CreateFile(char*, char*, int);

/********************************************
函数功能:生成[min,max)的整型随机数

*********************************************/
DWORD CreateRandom(int min, int max)
{
    return rand()%(max - min) + min;
}

/********************************************
函数功能:在一定时间内将write_time_table,read_time_table信息追加写入文件
参数
which : 0表示存储write_time_table, 1表示存储read_time_table
didd_time: 所花费的时间
size:读或写的大小(单位Bype)
*********************************************/
int StoreTable(char* dir, char* name, DWORD time)
{
int nRet = 0;
DWORD tmp = 0;
char file[128] = {'\0'};
sprintf(file, "%s\\%s", dir, name);
FILE* fd;
if(NULL == (fd = fopen(file, "w+")))
{
printf("error in StoreTable\n");
perror("fopen");
return -1;
}

while(true){
::Sleep(time);
fprintf(fd,"write table\n");
fprintf(fd,"\t\t\t[0,10) [10,20) [20,40) [40,80) [80,160) .....\n");
for(int i = 0; i < ARRAY_SIZE ; ++i)
{
if(0 != i){
fprintf(fd, "[%10ld,%10ld)\t", tmp,2*tmp);
tmp = 2*tmp;
}else{
fprintf(fd, "[         0,       32)\t");
tmp = 32;
}
for(int j = 0; j < ARRAY_SIZE; ++j)
{
nRet = fprintf(fd, "%6d\t", write_time_table[i][j]);
if(nRet < 0)
{
perror("fprintf");
}
}
fprintf(fd, "\n");
}

fprintf(fd,"read table\n");
fprintf(fd,"\t\t\t[0,10) [10,20) [20,40) [40,80) [80,160) .....\n");
for(i = 0; i < ARRAY_SIZE ; ++i)
{
if(0 != i){
fprintf(fd, "[%10ld,%10ld)\t", tmp,2*tmp);
tmp = 2*tmp;
}else{
fprintf(fd, "[        0,       32)\t");
tmp = 32;
}
for(int j = 0; j < ARRAY_SIZE; ++j)
{
nRet = fprintf(fd, "%6d\t", read_time_table[i][j]);
if(nRet < 0)
{
perror("fprintf");
}
}
fprintf(fd, "\n");
}
fprintf(fd,"\n\n");
}
fclose(fd);
return 0;
}

//打印信息线程函数入口
DWORD WINAPI GetTimeTable(LPVOID param)
{
char* dir = ((LPTHREAD_RECODE_PARAM)param)->dir;
char* name = ((LPTHREAD_RECODE_PARAM)param)->name;
DWORD time = ((LPTHREAD_RECODE_PARAM)param)->time;
StoreTable(dir, name, time);

    return 0;
}
/***************************************************
函数功能:更新记录
参数
which:  0 write_time_table 1 read_time_table
size:读或写的大小
diff_time:读或写用的时间
******************************************************/
int RecodeTime(int which, DWORD size, double diff_time)
{
int row, list; //row行,list列
if(32 > size)
{
row = 0;
}else{
row = (int)(log10(size)/log10(2) - 4);
}
if(row >= ARRAY_SIZE)
{
row = ARRAY_SIZE-1;
}

if(10.0 > diff_time)
{
list = 0;
}else{
list = (int)(log10(diff_time/10)/log10(2) + 1);
}
if(list >= ARRAY_SIZE)
{
list = ARRAY_SIZE-1;
}
//根据参数判断是更新哪张表(读表或者写表)
if(0 == which)
{
//更新write_time_table
++write_time_table[row][list];
}else if(1 ==  which){
//更新read_time_table
++read_time_table[row][list];
}else{
printf("error in RecodeTime: param is wrong\n");
}

return 0;
}

//写线程执行函数入口,只写特定的文件
DWORD WINAPI Write_thread(LPVOID param)
{
char file[128] = {0};
DWORD dwWritedDataSize = 0;
int nRet = 0;
DWORD offset = 0;

int num = ((LPTHREAD_WRITE_PARAM)param)->i;
DWORD file_size = ((LPTHREAD_WRITE_PARAM)param)->file_size;
DWORD write_range = ((LPTHREAD_WRITE_PARAM)param)->write_range;
char* dir = ((LPTHREAD_WRITE_PARAM)param)->dir;
sprintf(file,"%s\\%d.txt", dir, ((LPTHREAD_WRITE_PARAM)param)->i);
DWORD write_size;
HANDLE FileHandle;
int count = 0;
int begin_time = 0;
int end_time = 0;

while(true){
count = 2;//写的次数,这个是可变的
write_size = CreateRandom(0,write_range);//写文件的大小,这个是可变的

if(write_size < 0 || write_size >= write_range)
{
            assert(0);
            continue;
}

offset = CreateRandom(0, file_size-count*write_size-count);

if((offset + count * write_size > file_size)||(offset < 0))
{
assert(0);
}
FileHandle = Open_File(file);//fp指向文件的开始处
if(FileHandle == INVALID_HANDLE_VALUE)
    {
        printf("Error in CreateFile function, the reason is:[%ld]\n", GetLastError());
        ::Sleep(2000);
        continue;
    }

nRet = ::SetFilePointer(FileHandle, offset, NULL, FILE_BEGIN);
if ( nRet == 0xFFFFFFFF )
{
printf("error in SetFilePointer : reason:%d", GetLastError());
}

begin_time =GetTickCount();
for(int i = 0; i < count; i++)
{
nRet = ::WriteFile(FileHandle, buffer, write_size, &dwWritedDataSize, NULL);
if(!nRet)
{
printf("write data error:%ld\n",GetLastError());
}
}
end_time = ::GetTickCount();
Close_File(FileHandle);
//下面的if语句打印超过10ms的信息到屏幕上,主要用于调试
/*if(10 <= difftime(end_time, begin_time)){
printf("in write thread diff_time%f\n",difftime(end_time, begin_time));
}*/

RecodeTime(0, count*write_size, difftime(end_time, begin_time));
::Sleep(15);
}

    return 0;
}

//读线程执行函数入口,随机读已经存在的文件
DWORD WINAPI Read_thread(LPVOID param)
{
//初始化参数
DWORD dwReadedDataSize = 0;
int nRet = 0;
DWORD offset = 0;
int sum_files = ((LPTHREAD_READ_PARAM)param)->sum_files;
DWORD file_size = ((LPTHREAD_READ_PARAM)param)->file_size;
DWORD read_range = ((LPTHREAD_READ_PARAM)param)->read_range;
char* dir = ((LPTHREAD_READ_PARAM)param)->dir;
DWORD read_size = 0;
HANDLE FileHandle;
int count = 0;
int begin_time = 0;
int end_time = 0;
int read_file = 0;//标记正在读的文件
char file[128] = {0};

while(true)
{
count = 2;//这个是可变的,
read_size = CreateRandom(0,read_range);//读文件的大小,这个是可变的
if(0 > file_size-count*read_size)
{
printf("0 > file_size-count*read_size,please adjust the parm\n");
continue;
}

offset = CreateRandom(0, file_size-count*read_size-count);
read_file = CreateRandom(0, sum_files);//随机读取某个存在的文件
memset(file, '\0', sizeof(file));
sprintf(file,"%s\\%d.txt", dir, read_file);
FileHandle = Open_File(file);
if(FileHandle == INVALID_HANDLE_VALUE)
    {
        printf("Error in CreateFile function, the reason is:[%ld]\n", GetLastError());
        ::Sleep(2000);
        continue;
    }
::SetFilePointer(FileHandle, offset, NULL, FILE_BEGIN);
begin_time = GetTickCount();
for(int i = 0; i < count; ++i)
{
nRet = ::ReadFile(FileHandle, buffer, read_size, &dwReadedDataSize, NULL);
if(!nRet)
{
printf("read data error:%ld\n",GetLastError());
}
}
end_time = ::GetTickCount();
Close_File(FileHandle);

RecodeTime(1, count*read_size, difftime(end_time, begin_time));
::Sleep(15);
}

    return 0;
}

/***************************************************
函数功能:创建一个文件
参数: dir:路径
name:文件名
size:创建文件的大小(Byte)
******************************************************/
int CreateFile(char* dir, char *name, int size)
{
    char cmd[1024] = {'\0'};
sprintf(cmd,"fsutil file createnew %s\\%s.txt %d", dir, name, size);
    if(0 != system(cmd))
    {
        return -1;
    }

return 0;
}

/***************************************************
函数功能:打开一个文件
参数: file:文件的路径(包括文件名)
******************************************************/
HANDLE Open_File(char* file)
{
HANDLE m_FileHandle =  ::CreateFile(file,
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL,
OPEN_EXISTING, //打开已经存在的文件。
FILE_ATTRIBUTE_NORMAL,
NULL);
if(m_FileHandle == INVALID_HANDLE_VALUE)
    {
        int nRet = GetLastError();
        printf("Error in CreateFile function, the reason is:[%d]\n", nRet);
        ::Sleep(2000);
        return INVALID_HANDLE_VALUE;
    }
return m_FileHandle;
}

/***************************************************
函数功能:关闭一个文件
参数: HANDLE:文件句柄
******************************************************/
int Close_File(HANDLE mHandle)
{
::CloseHandle(mHandle);
return 0;
}

/***************************************************
函数功能:删除一个文件
参数: dir:文件的路径
name:文件的名字
******************************************************/
int DelFile(char* dir, char* name)
{
char cmd[1024] = {'\0'};
sprintf(cmd,"del %s\\%s", dir, name);
    if(0 != system(cmd))
    {
        printf("error in DelFile\n");
        return -1;
    }

return 0;
}

//主函数
int main(int argc, char* argv[])
{
int i;
int nRet = 0;
char name[1024];
    HANDLE hThread[MAX_THREAD] = {NULL};
    HANDLE hThreadRecode = NULL;
int seq_thread = 0;
char dir[128] = {'\0'};
char result_name[128] = {'\0'};
THREAD_WRITE_PARAM thread_write_param;
THREAD_READ_PARAM thread_read_param;
THREAD_RECODE_PARAM thread_recode_param;
LPTHREAD_WRITE_PARAM pDataWrite = &thread_write_param;
LPTHREAD_READ_PARAM pDataRead = &thread_read_param;
LPTHREAD_RECODE_PARAM pDataRecode = &thread_recode_param;
int save_time = 0;
for(i = 0; i < 1024; i++)
{
buffer[i] = '0' + i % 10;
}
//初始化read_time_table,write_time_table
for(i = 0; i < ARRAY_SIZE; ++i)
for(int j = 0; j < ARRAY_SIZE; ++j)
{
read_time_table[i][j] = 0;
write_time_table[i][j] = 0;
}

    //参数检查
    if(9 != argc)
    {
        printf("usage: 程序名 写文件线程数 写文件的范围 读文件的线程数 \
读文件的范围   文件的固定大小  文件的路径  结果文件的名称   多少时间保存一次结果\n");
printf("例如 2  1024  2  1024  20480  x:\\  result241.txt  2000\n");
return -1;
    }
int write_count = atol(argv[1]);
    DWORD write_range = atol(argv[2]);
    int read_count = atol(argv[3]);
    DWORD read_range = atol(argv[4]);
    DWORD file_size = atol(argv[5]);
strncpy(dir, argv[6], sizeof(dir));
strncpy(result_name, argv[7], sizeof(result_name));
save_time = atol(argv[8]);

char myresult_dir[128] = {"D:\\"};

/* int write_count = 2;
    DWORD write_range = 1024;
    int read_count = 2;
    DWORD read_range = 1024;
    DWORD file_size = 20480;
char dir[128] = "D:\\locattest";//该目录必须是已经存在的。
char result_name[1024] = "result.txt";
save_time = 1000;
*/

//创建写的文件,每个写文件线程单独写一个文件,单位Byte
    for(i = 0; i < write_count; i++){
      nRet = CreateFile(dir, itoa(i, name, 10), file_size);
if(0 != nRet){
printf("请您删除上次生成的文件(包括结果文件):%ld\n",GetLastError());
return -1;
}
}
    //创建打印time_table线程
    memset((void *)pDataRecode, '\0', sizeof(THREAD_RECODE_PARAM));
pDataRecode->dir = myresult_dir;
pDataRecode->name = result_name;
pDataRecode->time = save_time;
    hThreadRecode = CreateThread(NULL,0,GetTimeTable, pDataRecode,0,NULL);
::Sleep(1000);

//创建写线程
    for(i = 0; i < write_count; i++)
    {
      memset((void *)pDataWrite, '\0', sizeof(THREAD_WRITE_PARAM));
      pDataWrite->i = i;
pDataWrite->file_size = file_size;
pDataWrite->write_range = write_range;
pDataWrite->dir = dir;
      hThread[seq_thread++] = CreateThread(NULL,0,Write_thread, pDataWrite,0,NULL);
      Sleep(1000);
    }

//创建读线程
    for(i = 0; i < read_count; i++)
    {
      memset((void *)pDataRead, '\0', sizeof(THREAD_READ_PARAM));
      pDataRead->sum_files= write_count;//在这时,有几个写线程,就会有几个文件。
pDataRead->file_size = file_size;
pDataRead->read_range = read_range;
pDataRead->dir = dir;
      hThread[seq_thread++] = CreateThread(NULL,0,Read_thread, pDataRead,0,NULL);
      ::Sleep(1000);
    }
//等待所有线程退出
for(i = 0; i < MAX_THREAD; ++i)
{
if(NULL != hThread[i])
{
WaitForSingleObject(hThread[i],-1);
}else
{
break;
}
}
    WaitForSingleObject(hThreadRecode,-1);

//这里还要加一些资源的释放操作。
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值