准确获取CPU时间


#include "stdafx.h"

#include <Windows.h>
#include <io.h>
#include <direct.h>
#include <atlstr.h>

const char *_tmpfileName = "tmptestfile";
const char *TestStr = "0123456789";
const int   TestStrLen = 10;
const double Send_Rate = 0.1;
LONGLONG  Cpu_Freq = 0;
const __int64 Default_Data_Size = 1024*1024*100;
char strbuf[256];
int giNumLastOutput = 0;

/*
void OneLineOutput(const char *strput)
{
	for(int i=0;i<giNumLastOutput;i++) printf("\b");
	giNumLastOutput = printf(strput);
}*/

// 将TCHAR转化为char
char *TCHAR2char(_TCHAR *tchar)
{
	int wlen = lstrlen(tchar);
	char *_char = new char[wlen+1];
	if(_char == NULL)
	{
		printf("TCHAR2char new char[] error %d\n",GetLastError());
		return NULL;
	}
	WideCharToMultiByte(CP_ACP,0,tchar,-1,NULL,wlen,NULL,NULL);
	return _char;
}

// 字符串截断
char *CharCut(char *srcbuf)
{
	int pos;
	int len = strlen(srcbuf);
	for(pos = 0;pos<len;pos++)
	{
		if(srcbuf[pos] == '\n') break;
	}
	srcbuf[pos] = '\0';
	return srcbuf;
}

// 测试写速度
void TestWriteFile(char *filepath,__int64 totalSize);
// 测试读速度
void TestReadFile(char *filepath,__int64 totalSize);
// 获取CPU频率
LONGLONG GetCPUFreq();

// 获取时间戳
inline unsigned __int64 GetCycleCount()                
{
	__asm _emit 0x0F
		__asm _emit 0x31
}

void LogOut(char strbuf[])
{
	FILE *fp;
	TCHAR wstrAppPath[MAX_PATH]=_T("");
	char filePath[MAX_PATH]="";
	GetModuleFileName(NULL,wstrAppPath,MAX_PATH);
	CString str(wstrAppPath);
	int pos = str.ReverseFind('\\');
	wsprintf(wstrAppPath,_T("%s\\toollogout.txt"),str.Mid(0,pos));
	DWORD dwNum = WideCharToMultiByte(CP_ACP,NULL,wstrAppPath,-1,NULL,0,NULL,FALSE);
	WideCharToMultiByte(CP_ACP,NULL,wstrAppPath,-1,filePath,dwNum,NULL,FALSE);
	
	fopen_s(&fp,filePath,"r");
	if(fp != NULL) fclose(fp);

	if(fp == NULL)
	{
		fopen_s(&fp,filePath,"w");
	}
	else
	{
		fopen_s(&fp,filePath,"a+");
	}
	fwrite(strbuf,sizeof(char),strlen(strbuf),fp);
	fflush(fp);
	fclose(fp);
}

// 如果文件夹不存在就创建
void CreateDir(const char *dirpath)
{
	char mkpath[256]="";
	for(int i=0;i<(int)strlen(dirpath);i++)
	{
		mkpath[i] = dirpath[i];
		if(dirpath[i] == '\\')
		{	
			if(_access(mkpath,0) == -1)
			{
				_mkdir(mkpath);
			}
		}
	}

	if(_access(mkpath,0) == -1)
	{
		_mkdir(mkpath);
	}
}

// 从服务器管道接收数据线程
DWORD CALLBACK ReadFromServerPipeThread(LPVOID lpvParam){
	HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);    // 获取标准输入句柄
	char readbuff[256];
	DWORD dwLen = 0;
	while(ReadFile(hStdIn,readbuff,256,&dwLen,NULL))
	{

		if(dwLen > 0)
		{	
			CharCut(readbuff);
			if(strcmp(readbuff,"stop") == 0)
			{
				LogOut("need stop!");
				//OneLineOutput("Sub Program Stop!\n");
				printf("Sub Program Stop!\n");
				fflush(stdout);
				CloseHandle(hStdIn);
				exit(0);
			}
		}
	}
	CloseHandle(hStdIn);
	return 0;
}

// 主函数
int main(int argc, char* argv[])
{
	if(argc != 4)
	{
		sprintf_s(strbuf,256,"Usage:%s size read/write path\n",argv[0]);
		//OneLineOutput(strbuf);
		printf("Usage:%s size read/write path\n",argv[0]);
		fflush(stdout);
		return -1;
	}

	__int64 DataSize = (__int64)(atof(argv[1])*1024*1024);
	char *dirPath = argv[3];
	char filePath[128];

	LogOut("test");

	sprintf_s(filePath,128,"%s\\%s",dirPath,_tmpfileName);
	Cpu_Freq = GetCPUFreq();

	CreateDir(dirPath);      // 如果文件夹不存在就创建

	sprintf_s(strbuf,256,"DataSize=%I64d\n",DataSize);
	LogOut(strbuf);
	sprintf_s(strbuf,256,"Style:%s\n",argv[2]);
	LogOut(strbuf);

	DWORD dwThreadId = 0;
	HANDLE hThread = CreateThread(NULL,0,ReadFromServerPipeThread,NULL,0,&dwThreadId);

	fflush(stdout);
	if(strcmp(argv[2],"w") == 0)      
		TestWriteFile(filePath,DataSize);
	else if(strcmp(argv[2],"r") == 0) 
		TestReadFile(filePath,DataSize);

	printf("done\n");
	fflush(stdout);
	Sleep(100);
	//OneLineOutput("done\n");
	printf("done\n");
	fflush(stdout);
	Sleep(100);
	CloseHandle(hThread);
	return 0;
}

// 测试写速度
void TestWriteFile(char *filepath,__int64 totalSize)
{

	__int64 _sizeWriten = 0;                                // 已经写入的数据大小
	__int64 _sizeLastWriten = 0;                            // 上次写入的数据大小
	__int64 _cycTimes = totalSize / TestStrLen;             // 计算循环次数
	__int64 _sendSize = (__int64)(totalSize * Send_Rate)<(__int64)(10*1024*1024)?(__int64)(totalSize * Send_Rate):(__int64)(10*1024*1024);   // 计算发送超限
	char strWriteSpd[128];                                 // 写速度字符串
	__int64 _CycStartCnt = 0,_CycCurCnt = 0;
	double _timeS = 0;
	double _sizeWritenM,_curWriteSpeed;
	char sendbuf[256] = { 0 };

	FILE *fp;
	if(fopen_s(&fp,filepath,"w+") != 0)
	{
		//sprintf_s(strbuf,256,"Can not open file %s\n",filepath);
		//OneLineOutput(strbuf);
		fprintf(stderr,"Can not open file %s\n",filepath);
		fflush(stderr);
		return;
	}

	_CycStartCnt = GetCycleCount();
	for(__int64 _i=0;_i<_cycTimes;_i++)
	{
		fwrite(TestStr,sizeof(char),TestStrLen,fp);		
		_sizeWriten += TestStrLen;
		if(_sizeWriten - _sizeLastWriten >= _sendSize)
		{
			_sizeLastWriten = _sizeWriten;

			_CycCurCnt = GetCycleCount();
			_timeS = (double)((_CycCurCnt - _CycStartCnt)*1.0/Cpu_Freq);   // 现在距起始的时间(S)
			_sizeWritenM = (double)(_sizeWriten*1.0/1024/1024);             // 已经写入的数据大小(M)
			_curWriteSpeed = _sizeWritenM/_timeS;                           // 现在的写入速度 M/S
			sprintf_s(sendbuf,sizeof(sendbuf),"[Written:%0.1fM,Speed:%0.2fM]/s\n",_sizeWritenM,_curWriteSpeed);
			printf(sendbuf);
			//OneLineOutput(sendbuf);
			fflush(stdout);
		}
	}
	_CycCurCnt = GetCycleCount();
	if(fp!=NULL) fclose(fp);

	_timeS = (double)((_CycCurCnt - _CycStartCnt)/Cpu_Freq*1.0);   // 现在距起始的时间(S)
	_sizeWritenM = (double)(_sizeWriten/1024*1.0/1024);             // 已经写入的数据大小(M)
	_curWriteSpeed = _sizeWritenM*1.0/_timeS;                           // 现在的写入速度 M/S
	sprintf_s(strWriteSpd,128,"[Written:%0.1fM,Speed:%0.2fM]/s\n",_sizeWritenM,_curWriteSpeed);
	printf(strWriteSpd);
	//OneLineOutput(strWriteSpd);
	fflush(stdout);
}

// 测试读速度
void TestReadFile(char *filepath,__int64 totalSize)
{
	char _strReadSpd[256];
	__int64 _sizeRead = 0;
	__int64 _sizeLastRead = 0;
	__int64 _sendSize = (__int64)(totalSize * Send_Rate)<(__int64)(10*1024*1024)?(__int64)(totalSize * Send_Rate):(__int64)(10*1024*1024); // 计算发送超限
	double  _sizeReadM = 0;
	double _timeS = 0;
	double _curReadSpd = 0;
	__int64 _startCycCnt = 0,_curCycCnt = 0;
	int numRead = 0;
	char sendbuf[256] = { 0 };

	FILE *fp;
	fopen_s(&fp,filepath,"r");
	if(fp == NULL)
	{
		sprintf_s(strbuf,256,"can not open file %s!\n",filepath);
		//OneLineOutput(strbuf);
		printf("can not open file %s!\n",filepath);
		fflush(stdout);
		return;
	}

	_startCycCnt = GetCycleCount();
	while((numRead = fread(_strReadSpd,sizeof(char),256,fp)))
	{
		_sizeRead += numRead;
		if(_sizeRead - _sizeLastRead >= _sendSize)
		{
			_sizeLastRead = _sizeRead;

			_sizeReadM = (double)(_sizeRead/1024*1.0/1024);
			_curCycCnt = GetCycleCount();
			_timeS = double((_curCycCnt - _startCycCnt)*1.0/Cpu_Freq);
			_curReadSpd = _sizeReadM/_timeS;
			sprintf_s(sendbuf,sizeof(sendbuf),"[Read:%0.1fM,Speed:%0.2fM]/s\n",_sizeReadM,_curReadSpd);
			printf(sendbuf);
			//OneLineOutput(sendbuf);
			fflush(stdout);
		}
	}
	_curCycCnt = GetCycleCount();

	if(fp!=NULL) fclose(fp);
	_sizeReadM = (double)(_sizeRead/1024*1.0/1024);
	_timeS = double((_curCycCnt - _startCycCnt)*1.0/Cpu_Freq);
	_curReadSpd = _sizeReadM/_timeS;
	sprintf_s(_strReadSpd,256,"[Read:%0.1fM,Speed:%0.2fM]/s\n",_sizeReadM,_curReadSpd);
	//OneLineOutput(_strReadSpd);
	printf(_strReadSpd);
	fflush(stdout);
}


// 获取CPU频率
LONGLONG GetCPUFreq()
{
	DWORD low1 = 0,high1 = 0, low2 = 0, high2 = 0;

	LARGE_INTEGER fq,st,ed;

	::QueryPerformanceFrequency(&fq); // 精确计时,返回(硬件支持的高精度计数器)
	::QueryPerformanceCounter(&st);   // 获取起始时间

	__asm
	{
		rdtsc
			mov low1,eax
			mov high1,edx
	}
	Sleep(1000);
	::QueryPerformanceCounter(&ed);   // 获取结束时间

	__asm
	{
		rdtsc         // 读取CPU的时间戳计数器
			mov low2,eax
			mov high2,edx
	}

	// 将CPU的时间周期数转化为64位整数
	LONGLONG begin = (LONGLONG)high1<<32 | low1;
	LONGLONG end   = (LONGLONG)high2<<32 | low2;

	return (end - begin)*fq.QuadPart/(ed.QuadPart-st.QuadPart);
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值