ディスクのアクセス速度の測定

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

ディスクのアクセス速度の測定

#1

投稿記事 by みけCAT » 13年前

Dev-C++4.9.9.2、gcc version 3.4.2 (mingw-special)です。
Windows Vista Home Premium SP2 32ビットです。
Diskeeper 2011 Professionalをインストールしてあります。
C言語でディスクのアクセス速度を測定するプログラムを作りたいと思いました。
現在のプログラムだと、書き込み速度はほぼ正しい値が出るのですが、読み込み速度がおかしいです。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#if defined(__WIN32__) || defined(__WIN64__)
#include <windows.h>
long long getzikan(void) {
	return (long long)GetTickCount();
}
#else
#include <sys/time.h>
long long getzikan(void) {
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return (long long)tv.tv_sec*1000LL+
		(long long)tv.tv_usec/1000000LL;
}
#endif

enum {
	DATA_00,
	DATA_FF,
	DATA_RAND
};

int main(int argc,char* argv[]) {
	char* buf;
	char* filename="test.dat";
	long bufsize=512;
	long calcsize=50*1024*1024;
	long realsize;
	double speed;
	long long starttime;
	long long endtime;
	int i,j;
	int writenum;
	int datatype=DATA_RAND;
	int parseerror=0;
	char* strend;
	FILE* fp;
	/*コマンドライン引数のパース*/
	for(i=1;i<argc;i++) {
		if(i<argc-1) {
			if(strcmp(argv[i],"-f")==0) {
				filename=argv[i+1];
				i++;
			} else if(strcmp(argv[i],"-b")==0) {
				bufsize=strtol(argv[i+1],&strend,10);
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-s")==0) {
				calcsize=strtol(argv[i+1],&strend,10)*1024*1024;
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-d")==0) {
				if(strcmp(argv[i+1],"0")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"ff")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"rand")==0) {
					datatype=DATA_RAND;
					i++;
				} else {
					parseerror=1;
					break;
				}
			} else {
				parseerror=1;
				break;
			}
		} else {
			parseerror=1;
			break;
		}
	}
	if(parseerror) {
		fprintf(stderr,"Usage: calcacspeed [-f filename] "
			"[-b buffersize] [-s filesize] [-d datatype]\n");
		fprintf(stderr,"filename  :測定に使用するファイル名です。\n");
		fprintf(stderr,"           既存ファイルの場合、削除されます。\n");
		fprintf(stderr,"buffersize:一度に書き込むバイト数です。\n");
		fprintf(stderr,"filesize  :測定に使用するファイルサイズです。MB単位です。\n");
		fprintf(stderr,"datatype  :測定に使用するデータタイプです。\n");
		fprintf(stderr,"以下の中から指定します。\n");
		fprintf(stderr,"0   :全て0x00です。\n");
		fprintf(stderr,"ff  :全て0xffです。\n");
		fprintf(stderr,"rand:ランダムデータです。\n");
		fprintf(stderr,"デフォルト値は、\n");
		fprintf(stderr,"filename  :test.dat\n");
		fprintf(stderr,"buffersize:512\n");
		fprintf(stderr,"filesize  :50\n");
		fprintf(stderr,"datatype  :rand\n");
		fprintf(stderr,"です。\n"); 
		return 1;
	}
	/*バッファの確保*/
	buf=malloc(bufsize);
	if(buf==NULL) {
		fprintf(stderr,"バッファの確保に失敗しました。\n");
		return 1; 
	}
	/*時間の測定*/
	realsize=0;
	srand((unsigned int)time(NULL));
	writenum=calcsize/bufsize;
	realsize=writenum*bufsize;
	if(datatype==DATA_00) {
		for(j=0;j<bufsize;j++)buf[j]=0x00;
	} else if(datatype==DATA_FF) {
		for(j=0;j<bufsize;j++)buf[j]=0xff;
	}
	/*書き込み時間の測定*/
	starttime=getzikan();
	fp=fopen(filename,"wb");
	if(fp==NULL) {
		fprintf(stderr,"ファイルオープン(書き込み)に失敗しました。\n");
		free(buf);
		return 1;
	}
	for(i=0;i<writenum;i++) {
		if(datatype==DATA_RAND) {
			for(j=0;j<bufsize;j++)buf[j]=rand()&0xff;
		}
		if(fwrite(buf,bufsize,1,fp)!=1) {
			fprintf(stderr,"ファイル書き込みに失敗しました。\n");
			free(buf);
			return 1; 
		}
	}
	fclose(fp);
	endtime=getzikan();
	printf("書き込み時間\n");
	printf("%lldms\n",endtime-starttime);
	printf("書き込み速度\n");
	if(endtime==starttime) {
		printf("速すぎるため計測不能です。\n");
	} else {
		speed=(double)realsize*1000/(double)(endtime-starttime);
		printf("1MB=1024*1024Bとして\n");
		printf("%gMB/S\n",speed/1024/1024);
		printf("1MB=1000*1000Bとして\n");
		printf("%gMB/S\n",speed/1000/1000);
	}
	/*読み込み時間の測定*/
	starttime=getzikan();
	fp=fopen(filename,"rb");
	if(fp==NULL) {
		fprintf(stderr,"ファイルオープン(読み込み)に失敗しました。\n");
		free(buf);
		return 1; 
	}
	for(i=0;i<writenum;i++) {
		if(fread(buf,bufsize,1,fp)!=1) {
			fprintf(stderr,"ファイル読み込みに失敗しました。\n");
			free(buf);
			return 1; 
		}
	}
	fclose(fp);
	endtime=getzikan();
	printf("読み込み時間\n");
	printf("%lldms\n",endtime-starttime);
	printf("読み込み速度\n");
	if(endtime==starttime) {
		printf("速すぎるため計測不能です。\n");
	} else {
		speed=(double)realsize*1000/(double)(endtime-starttime);
		printf("1MB=1024*1024Bとして\n");
		printf("%gMB/S\n",speed/1024/1024);
		printf("1MB=1000*1000Bとして\n");
		printf("%gMB/S\n",speed/1000/1000);
	}
	/*ファイルの削除*/
	if(remove(filename)) {
		fprintf(stderr,"ファイルの削除に失敗しました。\n");
	}
	/*バッファの開放*/
	free(buf);
	/*正常終了*/
	return 0;
}
このプログラムを実行すると、次のようになります。

コード:

F:\C\calcacspeed>calcacspeed -f D:\test.dat -s 100
書き込み時間
3229ms
書き込み速度
1MB=1024*1024Bとして
30.9693MB/S
1MB=1000*1000Bとして
32.4737MB/S
読み込み時間
234ms
読み込み速度
1MB=1024*1024Bとして
427.35MB/S
1MB=1000*1000Bとして
448.109MB/S
同じDドライブをCrystalDiskMarkで測定すると、次のようになります。

コード:

-----------------------------------------------------------------------
CrystalDiskMark 3.0.1 (C) 2007-2010 hiyohiyo
                           Crystal Dew World : http://crystalmark.info/
-----------------------------------------------------------------------
* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

           Sequential Read :    30.236 MB/s
          Sequential Write :    30.705 MB/s
         Random Read 512KB :    16.834 MB/s
        Random Write 512KB :    20.223 MB/s
    Random Read 4KB (QD=1) :     0.361 MB/s [    88.2 IOPS]
   Random Write 4KB (QD=1) :     0.957 MB/s [   233.5 IOPS]
   Random Read 4KB (QD=32) :     0.724 MB/s [   176.8 IOPS]
  Random Write 4KB (QD=32) :     1.087 MB/s [   265.5 IOPS]

  Test : 100 MB [D: 94.5% (113.3/119.9 GB)] (x1)
  Date : 2011/11/19 21:49:14
    OS : Windows Vista Home Premium Edition SP2 [6.0 Build 6002] (x86)
  
原因はなんでしょうか?
わかりましたら教えていただければ幸いです。
よろしくお願いします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: ディスクのアクセス速度の測定

#2

投稿記事 by beatle » 13年前

filenameのファイルに書き込んだあと、同じファイルから読み込んでいるのでメモリにキャッシュされているとか。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ディスクのアクセス速度の測定

#3

投稿記事 by みけCAT » 13年前

ファイルをリネームしてみましたが、変わりません。
解決策は無いのでしょうか?
よろしくお願いします。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#if defined(__WIN32__) || defined(__WIN64__)
#include <windows.h>
long long getzikan(void) {
	return (long long)GetTickCount();
}
#else
#include <sys/time.h>
long long getzikan(void) {
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return (long long)tv.tv_sec*1000LL+
		(long long)tv.tv_usec/1000000LL;
}
#endif

enum {
	DATA_00,
	DATA_FF,
	DATA_RAND
};

int main(int argc,char* argv[]) {
	char* buf;
	char* filename="test.dat";
	char* filename2=NULL;
	long bufsize=512;
	long calcsize=50*1024*1024;
	long realsize;
	double speed;
	long long starttime;
	long long endtime;
	int i,j;
	int writenum;
	int datatype=DATA_RAND;
	int parseerror=0;
	char* strend;
	FILE* fp;
	/*コマンドライン引数のパース*/
	for(i=1;i<argc;i++) {
		if(i<argc-1) {
			if(strcmp(argv[i],"-f")==0) {
				filename=argv[i+1];
				i++;
			} else if(strcmp(argv[i],"-f2")==0) {
				filename2=argv[i+1];
				i++;
			} else if(strcmp(argv[i],"-b")==0) {
				bufsize=strtol(argv[i+1],&strend,10);
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-s")==0) {
				calcsize=strtol(argv[i+1],&strend,10)*1024*1024;
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-d")==0) {
				if(strcmp(argv[i+1],"0")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"ff")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"rand")==0) {
					datatype=DATA_RAND;
					i++;
				} else {
					parseerror=1;
					break;
				}
			} else {
				parseerror=1;
				break;
			}
		} else {
			parseerror=1;
			break;
		}
	}
	if(parseerror) {
		fprintf(stderr,"Usage: calcacspeed [-f filename] [-f2 filename2]\n"
			"[-b buffersize] [-s filesize] [-d datatype]\n");
		fprintf(stderr,"filename  :測定に使用するファイル名です。\n");
		fprintf(stderr,"           既存ファイルの場合、削除されます。\n");
		fprintf(stderr,"filename2 :測定に使用するファイル名その2です。\n");
		fprintf(stderr,"           filenameに書き込んだあと、\n");
		fprintf(stderr,"           こちらにリネームして読み込みます。\n");
		fprintf(stderr,"           既存ファイルの場合、削除または失敗します。\n");
		fprintf(stderr,"buffersize:一度に書き込むバイト数です。\n");
		fprintf(stderr,"filesize  :測定に使用するファイルサイズです。MB単位です。\n");
		fprintf(stderr,"datatype  :測定に使用するデータタイプです。\n");
		fprintf(stderr,"以下の中から指定します。\n");
		fprintf(stderr,"0   :全て0x00です。\n");
		fprintf(stderr,"ff  :全て0xffです。\n");
		fprintf(stderr,"rand:ランダムデータです。\n");
		fprintf(stderr,"デフォルト値は、\n");
		fprintf(stderr,"filename  :test.dat\n");
		fprintf(stderr,"buffersize:512\n");
		fprintf(stderr,"filesize  :50\n");
		fprintf(stderr,"datatype  :rand\n");
		fprintf(stderr,"です。\n"); 
		return 1;
	}
	/*バッファの確保*/
	buf=malloc(bufsize);
	if(buf==NULL) {
		fprintf(stderr,"バッファの確保に失敗しました。\n");
		return 1; 
	}
	/*時間の測定*/
	realsize=0;
	srand((unsigned int)time(NULL));
	writenum=calcsize/bufsize;
	realsize=writenum*bufsize;
	if(datatype==DATA_00) {
		for(j=0;j<bufsize;j++)buf[j]=0x00;
	} else if(datatype==DATA_FF) {
		for(j=0;j<bufsize;j++)buf[j]=0xff;
	}
	/*書き込み時間の測定*/
	starttime=getzikan();
	fp=fopen(filename,"wb");
	if(fp==NULL) {
		fprintf(stderr,"ファイルオープン(書き込み)に失敗しました。\n");
		free(buf);
		return 1;
	}
	for(i=0;i<writenum;i++) {
		if(datatype==DATA_RAND) {
			for(j=0;j<bufsize;j++)buf[j]=rand()&0xff;
		}
		if(fwrite(buf,bufsize,1,fp)!=1) {
			fprintf(stderr,"ファイル書き込みに失敗しました。\n");
			free(buf);
			return 1; 
		}
	}
	fclose(fp);
	endtime=getzikan();
	printf("書き込み時間\n");
	printf("%lldms\n",endtime-starttime);
	printf("書き込み速度\n");
	if(endtime==starttime) {
		printf("速すぎるため計測不能です。\n");
	} else {
		speed=(double)realsize*1000/(double)(endtime-starttime);
		printf("1MB=1024*1024Bとして\n");
		printf("%gMB/S\n",speed/1024/1024);
		printf("1MB=1000*1000Bとして\n");
		printf("%gMB/S\n",speed/1000/1000);
	}
	/*ファイル名の変更*/
	if(filename2!=NULL) {
		if(rename(filename,filename2)) {
			fprintf(stderr,"ファイルのリネームに失敗しました。\n");
		} else {
			filename=filename2;
		}
	}
	/*読み込み時間の測定*/
	starttime=getzikan();
	fp=fopen(filename,"rb");
	if(fp==NULL) {
		fprintf(stderr,"ファイルオープン(読み込み)に失敗しました。\n");
		free(buf);
		return 1; 
	}
	for(i=0;i<writenum;i++) {
		if(fread(buf,bufsize,1,fp)!=1) {
			fprintf(stderr,"ファイル読み込みに失敗しました。\n");
			free(buf);
			return 1; 
		}
	}
	fclose(fp);
	endtime=getzikan();
	printf("読み込み時間\n");
	printf("%lldms\n",endtime-starttime);
	printf("読み込み速度\n");
	if(endtime==starttime) {
		printf("速すぎるため計測不能です。\n");
	} else {
		speed=(double)realsize*1000/(double)(endtime-starttime);
		printf("1MB=1024*1024Bとして\n");
		printf("%gMB/S\n",speed/1024/1024);
		printf("1MB=1000*1000Bとして\n");
		printf("%gMB/S\n",speed/1000/1000);
	}
	/*ファイルの削除*/
	if(remove(filename)) {
		fprintf(stderr,"ファイルの削除に失敗しました。\n");
	}
	/*バッファの開放*/
	free(buf);
	/*正常終了*/
	return 0;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: ディスクのアクセス速度の測定

#4

投稿記事 by softya(ソフト屋) » 13年前

CreateFileをつかってFILE_FLAG_NO_BUFFERINGで入出力しているって可能性は無いでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: ディスクのアクセス速度の測定

#5

投稿記事 by beatle » 13年前

リネームしたらファイルのキャッシュが無効になる保証はありますか?
リネームという操作はシステム側が認識しており、名前が変わっただけでファイルの中身は変わっていないのはシステム側は把握していますから、
変えた後の名前でアクセスしても、賢いシステムなら以前のファイル名のキャッシュをそのまま使ってもおかしくありません。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ディスクのアクセス速度の測定

#6

投稿記事 by みけCAT » 13年前

softya(ソフト屋) さんが書きました:CreateFileをつかってFILE_FLAG_NO_BUFFERINGで入出力しているって可能性は無いでしょうか?
どういうことでしょうか?
CreateFileとFILE_FLAG_NO_BUFFERINGを使うと処理がかなり遅くなってしまいました。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#if 1
#define USE_WIN_FILE_API
#endif

#if defined(__WIN32__) || defined(__WIN64__)
#include <windows.h>
long long getzikan(void) {
	return (long long)GetTickCount();
}
#else
#include <sys/time.h>
#ifdef USE_WIN_FILE_API
#undef USE_WIN_FILE_API
#endif
long long getzikan(void) {
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return (long long)tv.tv_sec*1000LL+
		(long long)tv.tv_usec/1000000LL;
}
#endif

enum {
	DATA_00,
	DATA_FF,
	DATA_RAND
};

int main(int argc,char* argv[]) {
	char* buf;
	char* filename="test.dat";
	char* filename2=NULL;
	long bufsize=512;
	long calcsize=50*1024*1024;
	long realsize;
	double speed;
	long long starttime;
	long long endtime;
	int i,j;
	int writenum;
	int datatype=DATA_RAND;
	int parseerror=0;
	char* strend;
#ifdef USE_WIN_FILE_API
	HANDLE fp;
	DWORD win_ac_size;
#else
	FILE* fp;
#endif
	/*コマンドライン引数のパース*/
	for(i=1;i<argc;i++) {
		if(i<argc-1) {
			if(strcmp(argv[i],"-f")==0) {
				filename=argv[i+1];
				i++;
			} else if(strcmp(argv[i],"-f2")==0) {
				filename2=argv[i+1];
				i++;
			} else if(strcmp(argv[i],"-b")==0) {
				bufsize=strtol(argv[i+1],&strend,10);
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-s")==0) {
				calcsize=strtol(argv[i+1],&strend,10)*1024*1024;
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-d")==0) {
				if(strcmp(argv[i+1],"0")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"ff")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"rand")==0) {
					datatype=DATA_RAND;
					i++;
				} else {
					parseerror=1;
					break;
				}
			} else {
				parseerror=1;
				break;
			}
		} else {
			parseerror=1;
			break;
		}
	}
	if(parseerror) {
		fprintf(stderr,"Usage: calcacspeed [-f filename] [-f2 filename2]\n"
			"[-b buffersize] [-s filesize] [-d datatype]\n");
		fprintf(stderr,"filename  :測定に使用するファイル名です。\n");
		fprintf(stderr,"           既存ファイルの場合、削除されます。\n");
		fprintf(stderr,"filename2 :測定に使用するファイル名その2です。\n");
		fprintf(stderr,"           filenameに書き込んだあと、\n");
		fprintf(stderr,"           こちらにリネームして読み込みます。\n");
		fprintf(stderr,"           既存ファイルの場合、削除または失敗します。\n");
		fprintf(stderr,"buffersize:一度に書き込むバイト数です。\n");
		fprintf(stderr,"filesize  :測定に使用するファイルサイズです。MB単位です。\n");
		fprintf(stderr,"datatype  :測定に使用するデータタイプです。\n");
		fprintf(stderr,"以下の中から指定します。\n");
		fprintf(stderr,"0   :全て0x00です。\n");
		fprintf(stderr,"ff  :全て0xffです。\n");
		fprintf(stderr,"rand:ランダムデータです。\n");
		fprintf(stderr,"デフォルト値は、\n");
		fprintf(stderr,"filename  :test.dat\n");
		fprintf(stderr,"buffersize:512\n");
		fprintf(stderr,"filesize  :50\n");
		fprintf(stderr,"datatype  :rand\n");
		fprintf(stderr,"です。\n"); 
		return 1;
	}
	/*バッファの確保*/
	buf=malloc(bufsize);
	if(buf==NULL) {
		fprintf(stderr,"バッファの確保に失敗しました。\n");
		return 1; 
	}
	/*時間の測定*/
	realsize=0;
	srand((unsigned int)time(NULL));
	writenum=calcsize/bufsize;
	realsize=writenum*bufsize;
	if(datatype==DATA_00) {
		for(j=0;j<bufsize;j++)buf[j]=0x00;
	} else if(datatype==DATA_FF) {
		for(j=0;j<bufsize;j++)buf[j]=0xff;
	}
	/*書き込み時間の測定*/
	starttime=getzikan();
#ifdef USE_WIN_FILE_API
	fp=CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
		FILE_ATTRIBUTE_NORMAL |
		FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN,0);
	if(fp==INVALID_HANDLE_VALUE) {
		fprintf(stderr,"ファイルオープンに失敗しました。\n");
		free(buf);
		return 1; 
	}
	for(i=0;i<writenum;i++) {
		if(!WriteFile(fp,buf,bufsize,&win_ac_size,NULL) ||
				win_ac_size!=bufsize) {
			fprintf(stderr,"ファイル書き込みに失敗しました。\n");
			free(buf);
			return 1;
		}
	}
	CloseHandle(fp);
#else
	fp=fopen(filename,"wb");
	if(fp==NULL) {
		fprintf(stderr,"ファイルオープン(書き込み)に失敗しました。\n");
		free(buf);
		return 1;
	}
	for(i=0;i<writenum;i++) {
		if(datatype==DATA_RAND) {
			for(j=0;j<bufsize;j++)buf[j]=rand()&0xff;
		}
		if(fwrite(buf,bufsize,1,fp)!=1) {
			fprintf(stderr,"ファイル書き込みに失敗しました。\n");
			free(buf);
			return 1; 
		}
	}
	fclose(fp);
#endif
	endtime=getzikan();
	printf("書き込み時間\n");
	printf("%lldms\n",endtime-starttime);
	printf("書き込み速度\n");
	if(endtime==starttime) {
		printf("速すぎるため計測不能です。\n");
	} else {
		speed=(double)realsize*1000/(double)(endtime-starttime);
		printf("1MB=1024*1024Bとして\n");
		printf("%gMB/S\n",speed/1024/1024);
		printf("1MB=1000*1000Bとして\n");
		printf("%gMB/S\n",speed/1000/1000);
	}
	/*ファイル名の変更*/
	if(filename2!=NULL) {
		if(rename(filename,filename2)) {
			fprintf(stderr,"ファイルのリネームに失敗しました。\n");
		} else {
			filename=filename2;
		}
	}
	/*読み込み時間の測定*/
	starttime=getzikan();
#ifdef USE_WIN_FILE_API
	fp=CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL |
		FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN,0);
	if(fp==INVALID_HANDLE_VALUE) {
		fprintf(stderr,"ファイルオープンに失敗しました。\n");
		free(buf);
		return 1; 
	}
	for(i=0;i<writenum;i++) {
		if(!ReadFile(fp,buf,bufsize,&win_ac_size,NULL) ||
				win_ac_size!=bufsize) {
			fprintf(stderr,"ファイル読み込みに失敗しました。\n");
			free(buf);
			return 1;
		}
	}
	CloseHandle(fp);
#else
	fp=fopen(filename,"rb");
	if(fp==NULL) {
		fprintf(stderr,"ファイルオープン(読み込み)に失敗しました。\n");
		free(buf);
		return 1; 
	}
	for(i=0;i<writenum;i++) {
		if(fread(buf,bufsize,1,fp)!=1) {
			fprintf(stderr,"ファイル読み込みに失敗しました。\n");
			free(buf);
			return 1; 
		}
	}
	fclose(fp);
#endif
	endtime=getzikan();
	printf("読み込み時間\n");
	printf("%lldms\n",endtime-starttime);
	printf("読み込み速度\n");
	if(endtime==starttime) {
		printf("速すぎるため計測不能です。\n");
	} else {
		speed=(double)realsize*1000/(double)(endtime-starttime);
		printf("1MB=1024*1024Bとして\n");
		printf("%gMB/S\n",speed/1024/1024);
		printf("1MB=1000*1000Bとして\n");
		printf("%gMB/S\n",speed/1000/1000);
	}
	/*ファイルの削除*/
	if(remove(filename)) {
		fprintf(stderr,"ファイルの削除に失敗しました。\n");
	}
	/*バッファの開放*/
	free(buf);
	/*正常終了*/
	return 0;
}
実行結果

コード:

D:\>F:\C\calcacspeed\calcacspeed
書き込み時間
30092ms
書き込み速度
1MB=1024*1024Bとして
1.66157MB/S
1MB=1000*1000Bとして
1.74228MB/S
読み込み時間
27862ms
読み込み速度
1MB=1024*1024Bとして
1.79456MB/S
1MB=1000*1000Bとして
1.88173MB/S
beatle さんが書きました:リネームしたらファイルのキャッシュが無効になる保証はありますか?
リネームという操作はシステム側が認識しており、名前が変わっただけでファイルの中身は変わっていないのはシステム側は把握していますから、
変えた後の名前でアクセスしても、賢いシステムなら以前のファイル名のキャッシュをそのまま使ってもおかしくありません。
やはりそうですか・・・。
解決は不可能なのでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

beatle
記事: 1281
登録日時: 13年前
住所: 埼玉
連絡を取る:

Re: ディスクのアクセス速度の測定

#7

投稿記事 by beatle » 13年前

書き込んだ後手動でコピーしてファイル名を変え、そのコピーしたファイルを読み込むようにしたらキャッシュはなくなる気がしますね。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ディスクのアクセス速度の測定

#8

投稿記事 by みけCAT » 13年前

beatle さんが書きました:書き込んだ後手動でコピーしてファイル名を変え、そのコピーしたファイルを読み込むようにしたらキャッシュはなくなる気がしますね。
改善しませんでした。
書き込んだファイルをバイナリエディタで適当に書き換えてもダメでした。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#if 0
#define USE_WIN_FILE_API
#endif

#if 0
#define USE_DOUBLE_FILE
#endif

#if defined(__WIN32__) || defined(__WIN64__)
#include <windows.h>
long long getzikan(void) {
	return (long long)GetTickCount();
}
#else
#include <sys/time.h>
#ifdef USE_WIN_FILE_API
#undef USE_WIN_FILE_API
#endif
long long getzikan(void) {
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return (long long)tv.tv_sec*1000LL+
		(long long)tv.tv_usec/1000000LL;
}
#endif

enum {
	DATA_00,
	DATA_FF,
	DATA_RAND
};

enum {
	MODE_READ,
	MODE_WRITE,
	MODE_BOTH
};

int main(int argc,char* argv[]) {
	char* buf;
	char* filename="test.dat";
#ifdef USE_DOUBLE_FILE
	char* filename2=NULL;
#endif
	long bufsize=512;
	long calcsize=50*1024*1024;
	long realsize;
	int mode=MODE_BOTH;
	double speed;
	long long starttime;
	long long endtime;
	int i,j;
	int writenum;
	int datatype=DATA_RAND;
	int parseerror=0;
	char* strend;
#ifdef USE_WIN_FILE_API
	HANDLE fp;
	DWORD win_ac_size;
#else
	FILE* fp;
#endif
	/*コマンドライン引数のパース*/
	for(i=1;i<argc;i++) {
		if(i<argc-1) {
			if(strcmp(argv[i],"-f")==0) {
				filename=argv[i+1];
				i++;
#ifdef USE_DOUBLE_FILE
			} else if(strcmp(argv[i],"-f2")==0) {
				filename2=argv[i+1];
				i++;
#endif
			} else if(strcmp(argv[i],"-b")==0) {
				bufsize=strtol(argv[i+1],&strend,10);
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-s")==0) {
				calcsize=strtol(argv[i+1],&strend,10)*1024*1024;
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-d")==0) {
				if(strcmp(argv[i+1],"0")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"ff")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"rand")==0) {
					datatype=DATA_RAND;
					i++;
				} else {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-m")==0) {
				if(strcmp(argv[i+1],"read")==0) {
					mode=MODE_READ;
					i++;
				} else if(strcmp(argv[i+1],"write")==0) {
					mode=MODE_WRITE;
					i++;
				} else if(strcmp(argv[i+1],"both")==0) {
					mode=MODE_BOTH;
					i++;
				} else {
					parseerror=1;
					break;
				}
			} else {
				parseerror=1;
				break;
			}
		} else {
			parseerror=1;
			break;
		}
	}
	if(parseerror) {
#ifdef USE_DOUBLE_FILE
		fprintf(stderr,"Usage: calcacspeed [-f filename] [-f2 filename2]\n"
			"[-b buffersize] [-s filesize] [-d datatype] [-m mode]\n");
#else
		fprintf(stderr,"Usage: calcacspeed [-f filename]\n"
			"[-b buffersize] [-s filesize] [-d datatype] [-m mode]\n");
#endif
		fprintf(stderr,"filename  :測定に使用するファイル名です。\n");
		fprintf(stderr,"           既存ファイルの場合、削除されます。\n");
#ifdef USE_DOUBLE_FILE
		fprintf(stderr,"filename2 :測定に使用するファイル名その2です。\n");
		fprintf(stderr,"           filenameに書き込んだあと、\n");
		fprintf(stderr,"           こちらにリネームして読み込みます。\n");
		fprintf(stderr,"           既存ファイルの場合、削除または失敗します。\n");
#endif
		fprintf(stderr,"buffersize:一度に書き込むバイト数です。\n");
		fprintf(stderr,"filesize  :測定に使用するファイルサイズです。MB単位です。\n");
		fprintf(stderr,"datatype  :測定に使用するデータタイプです。\n");
		fprintf(stderr,"以下の中から指定します。\n");
		fprintf(stderr,"0   :全て0x00です。\n");
		fprintf(stderr,"ff  :全て0xffです。\n");
		fprintf(stderr,"rand:ランダムデータです。\n");
		fprintf(stderr,"mode      :測定モードです。\n");
		fprintf(stderr,"以下の中から指定します。\n");
		fprintf(stderr,"read :読み込みのみを行います。\n");
		fprintf(stderr,"write:書き込みのみを行います。\n");
		fprintf(stderr,"both :両方のテストを行います。\n");
		fprintf(stderr,"デフォルト値は、\n");
		fprintf(stderr,"filename  :test.dat\n");
		fprintf(stderr,"buffersize:512\n");
		fprintf(stderr,"filesize  :50\n");
		fprintf(stderr,"datatype  :rand\n");
		fprintf(stderr,"mode      :both\n");
		fprintf(stderr,"です。\n"); 
		return 1;
	}
	/*バッファの確保*/
	buf=malloc(bufsize);
	if(buf==NULL) {
		fprintf(stderr,"バッファの確保に失敗しました。\n");
		return 1; 
	}
	/*時間の測定*/
	realsize=0;
	srand((unsigned int)time(NULL));
	writenum=calcsize/bufsize;
	realsize=writenum*bufsize;
	if(datatype==DATA_00) {
		for(j=0;j<bufsize;j++)buf[j]=0x00;
	} else if(datatype==DATA_FF) {
		for(j=0;j<bufsize;j++)buf[j]=0xff;
	}
	/*書き込み時間の測定*/
	if(mode!=MODE_READ) {
		starttime=getzikan();
#ifdef USE_WIN_FILE_API
		fp=CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL |
			FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN,0);
		if(fp==INVALID_HANDLE_VALUE) {
			fprintf(stderr,"ファイルオープンに失敗しました。\n");
			free(buf);
			return 1; 
		}
		for(i=0;i<writenum;i++) {
			if(!WriteFile(fp,buf,bufsize,&win_ac_size,NULL) ||
					win_ac_size!=bufsize) {
				fprintf(stderr,"ファイル書き込みに失敗しました。\n");
				free(buf);
				return 1;
			}
		}
		CloseHandle(fp);
#else
		fp=fopen(filename,"wb");
		if(fp==NULL) {
			fprintf(stderr,"ファイルオープン(書き込み)に失敗しました。\n");
			free(buf);
			return 1;
		}
		for(i=0;i<writenum;i++) {
			if(datatype==DATA_RAND) {
				for(j=0;j<bufsize;j++)buf[j]=rand()&0xff;
			}
			if(fwrite(buf,bufsize,1,fp)!=1) {
				fprintf(stderr,"ファイル書き込みに失敗しました。\n");
				free(buf);
				return 1; 
			}
		}
		fclose(fp);
#endif
		endtime=getzikan();
		printf("書き込み時間\n");
		printf("%lldms\n",endtime-starttime);
		printf("書き込み速度\n");
		if(endtime==starttime) {
			printf("速すぎるため計測不能です。\n");
		} else {
			speed=(double)realsize*1000/(double)(endtime-starttime);
			printf("1MB=1024*1024Bとして\n");
			printf("%gMB/S\n",speed/1024/1024);
			printf("1MB=1000*1000Bとして\n");
			printf("%gMB/S\n",speed/1000/1000);
		}
	}
#ifdef USE_DOUBLE_FILE
	/*ファイル名の変更*/
	if(filename2!=NULL) {
		if(rename(filename,filename2)) {
			fprintf(stderr,"ファイルのリネームに失敗しました。\n");
		} else {
			filename=filename2;
		}
	}
#endif
	/*読み込み時間の測定*/
	if(mode!=MODE_WRITE) {
		starttime=getzikan();
#ifdef USE_WIN_FILE_API
		fp=CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL |
			FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN,0);
		if(fp==INVALID_HANDLE_VALUE) {
			fprintf(stderr,"ファイルオープンに失敗しました。\n");
			free(buf);
			return 1; 
		}
		for(i=0;i<writenum;i++) {
			if(!ReadFile(fp,buf,bufsize,&win_ac_size,NULL) ||
					win_ac_size!=bufsize) {
				fprintf(stderr,"ファイル読み込みに失敗しました。\n");
				free(buf);
				return 1;
			}
		}
		CloseHandle(fp);
#else
		fp=fopen(filename,"rb");
		if(fp==NULL) {
			fprintf(stderr,"ファイルオープン(読み込み)に失敗しました。\n");
			free(buf);
			return 1; 
		}
		for(i=0;i<writenum;i++) {
			if(fread(buf,bufsize,1,fp)!=1) {
				fprintf(stderr,"ファイル読み込みに失敗しました。\n");
				free(buf);
				return 1; 
			}
		}
		fclose(fp);
#endif
		endtime=getzikan();
		printf("読み込み時間\n");
		printf("%lldms\n",endtime-starttime);
		printf("読み込み速度\n");
		if(endtime==starttime) {
			printf("速すぎるため計測不能です。\n");
		} else {
			speed=(double)realsize*1000/(double)(endtime-starttime);
			printf("1MB=1024*1024Bとして\n");
			printf("%gMB/S\n",speed/1024/1024);
			printf("1MB=1000*1000Bとして\n");
			printf("%gMB/S\n",speed/1000/1000);
		}
	}
	/*ファイルの削除*/
	if(mode==MODE_BOTH) {
		if(remove(filename)) {
			fprintf(stderr,"ファイルの削除に失敗しました。\n");
		}
	}
	/*バッファの開放*/
	free(buf);
	/*正常終了*/
	return 0;
}
実行結果

コード:

D:\>F:\C\calcacspeed\calcacspeed -m write
書き込み時間
1451ms
書き込み速度
1MB=1024*1024Bとして
34.459MB/S
1MB=1000*1000Bとして
36.1329MB/S

D:\>F:\C\calcacspeed\calcacspeed -f testdayo.dat -m read
読み込み時間
94ms
読み込み速度
1MB=1024*1024Bとして
531.915MB/S
1MB=1000*1000Bとして
557.753MB/S
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: ディスクのアクセス速度の測定

#9

投稿記事 by softya(ソフト屋) » 13年前

CreateFileとFILE_FLAG_NO_BUFFERINGを使うと処理がかなり遅くなってしまいました
CrystalDiskMarkのソースコードを見て見ましたが「FILE_FLAG_NO_BUFFERING」でやっているみたいですよ。
シーケンシャルリード時のパラメータです。
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ディスクのアクセス速度の測定

#10

投稿記事 by みけCAT » 13年前

バッファサイズを増やしたら近い結果が出ました。
ありがとうございます。
Linux上でのテストはまた機会があればやります。

コード:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#if 1
#define USE_WIN_FILE_API
#endif

#if 0
#define WIN_FILE_API_BUFFERING
#endif

#if 0
#define USE_DOUBLE_FILE
#endif

#if defined(__WIN32__) || defined(__WIN64__)
#include <windows.h>
long long getzikan(void) {
	return (long long)GetTickCount();
}
#else
#include <sys/time.h>
#ifdef USE_WIN_FILE_API
#undef USE_WIN_FILE_API
#endif
long long getzikan(void) {
	struct timeval tv;
	gettimeofday(&tv,NULL);
	return (long long)tv.tv_sec*1000LL+
		(long long)tv.tv_usec/1000000LL;
}
#endif

enum {
	DATA_00,
	DATA_FF,
	DATA_RAND
};

enum {
	MODE_READ,
	MODE_WRITE,
	MODE_BOTH
};

int main(int argc,char* argv[]) {
	char* buf;
	char* filename="test.dat";
#ifdef USE_DOUBLE_FILE
	char* filename2=NULL;
#endif
	long bufsize=512000;
	long calcsize=50*1024*1024;
	long realsize;
	int mode=MODE_BOTH;
	double speed;
	long long starttime;
	long long endtime;
	int i,j;
	int writenum;
	int datatype=DATA_RAND;
	int parseerror=0;
	char* strend;
#ifdef USE_WIN_FILE_API
	HANDLE fp;
	DWORD win_ac_size;
#else
	FILE* fp;
#endif
	/*コマンドライン引数のパース*/
	for(i=1;i<argc;i++) {
		if(i<argc-1) {
			if(strcmp(argv[i],"-f")==0) {
				filename=argv[i+1];
				i++;
#ifdef USE_DOUBLE_FILE
			} else if(strcmp(argv[i],"-f2")==0) {
				filename2=argv[i+1];
				i++;
#endif
			} else if(strcmp(argv[i],"-b")==0) {
				bufsize=strtol(argv[i+1],&strend,10);
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-s")==0) {
				calcsize=strtol(argv[i+1],&strend,10)*1024*1024;
				i++;
				if(*strend!='\0') {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-d")==0) {
				if(strcmp(argv[i+1],"0")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"ff")==0) {
					datatype=DATA_00;
					i++;
				} else if(strcmp(argv[i+1],"rand")==0) {
					datatype=DATA_RAND;
					i++;
				} else {
					parseerror=1;
					break;
				}
			} else if(strcmp(argv[i],"-m")==0) {
				if(strcmp(argv[i+1],"read")==0) {
					mode=MODE_READ;
					i++;
				} else if(strcmp(argv[i+1],"write")==0) {
					mode=MODE_WRITE;
					i++;
				} else if(strcmp(argv[i+1],"both")==0) {
					mode=MODE_BOTH;
					i++;
				} else {
					parseerror=1;
					break;
				}
			} else {
				parseerror=1;
				break;
			}
		} else {
			parseerror=1;
			break;
		}
	}
	if(parseerror) {
#ifdef USE_DOUBLE_FILE
		fprintf(stderr,"Usage: calcacspeed [-f filename] [-f2 filename2]\n"
			"[-b buffersize] [-s filesize] [-d datatype] [-m mode]\n");
#else
		fprintf(stderr,"Usage: calcacspeed [-f filename]\n"
			"[-b buffersize] [-s filesize] [-d datatype] [-m mode]\n");
#endif
		fprintf(stderr,"filename  :測定に使用するファイル名です。\n");
		fprintf(stderr,"           既存ファイルの場合、削除されます。\n");
#ifdef USE_DOUBLE_FILE
		fprintf(stderr,"filename2 :測定に使用するファイル名その2です。\n");
		fprintf(stderr,"           filenameに書き込んだあと、\n");
		fprintf(stderr,"           こちらにリネームして読み込みます。\n");
		fprintf(stderr,"           既存ファイルの場合、削除または失敗します。\n");
#endif
		fprintf(stderr,"buffersize:一度に書き込むバイト数です。\n");
		fprintf(stderr,"filesize  :測定に使用するファイルサイズです。MB単位です。\n");
		fprintf(stderr,"datatype  :測定に使用するデータタイプです。\n");
		fprintf(stderr,"以下の中から指定します。\n");
		fprintf(stderr,"0   :全て0x00です。\n");
		fprintf(stderr,"ff  :全て0xffです。\n");
		fprintf(stderr,"rand:ランダムデータです。\n");
		fprintf(stderr,"mode      :測定モードです。\n");
		fprintf(stderr,"以下の中から指定します。\n");
		fprintf(stderr,"read :読み込みのみを行います。\n");
		fprintf(stderr,"write:書き込みのみを行います。\n");
		fprintf(stderr,"both :両方のテストを行います。\n");
		fprintf(stderr,"デフォルト値は、\n");
		fprintf(stderr,"filename  :test.dat\n");
		fprintf(stderr,"buffersize:512000\n");
		fprintf(stderr,"filesize  :50\n");
		fprintf(stderr,"datatype  :rand\n");
		fprintf(stderr,"mode      :both\n");
		fprintf(stderr,"です。\n"); 
		return 1;
	}
	/*バッファの確保*/
	buf=malloc(bufsize);
	if(buf==NULL) {
		fprintf(stderr,"バッファの確保に失敗しました。\n");
		return 1; 
	}
	/*時間の測定*/
	realsize=0;
	srand((unsigned int)time(NULL));
	writenum=calcsize/bufsize;
	realsize=writenum*bufsize;
	if(datatype==DATA_00) {
		for(j=0;j<bufsize;j++)buf[j]=0x00;
	} else if(datatype==DATA_FF) {
		for(j=0;j<bufsize;j++)buf[j]=0xff;
	}
	/*書き込み時間の測定*/
	if(mode!=MODE_READ) {
		starttime=getzikan();
#ifdef USE_WIN_FILE_API
#ifdef WIN_FILE_API_BUFFERING
		fp=CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0);
#else
		fp=CreateFile(filename,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL |
			FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN,0);
#endif
		if(fp==INVALID_HANDLE_VALUE) {
			fprintf(stderr,"ファイルオープンに失敗しました。\n");
			free(buf);
			return 1; 
		}
		for(i=0;i<writenum;i++) {
			if(!WriteFile(fp,buf,bufsize,&win_ac_size,NULL) ||
					win_ac_size!=bufsize) {
				fprintf(stderr,"ファイル書き込みに失敗しました。\n");
				free(buf);
				return 1;
			}
		}
		CloseHandle(fp);
#else
		fp=fopen(filename,"wb");
		if(fp==NULL) {
			fprintf(stderr,"ファイルオープン(書き込み)に失敗しました。\n");
			free(buf);
			return 1;
		}
		for(i=0;i<writenum;i++) {
			if(datatype==DATA_RAND) {
				for(j=0;j<bufsize;j++)buf[j]=rand()&0xff;
			}
			if(fwrite(buf,bufsize,1,fp)!=1) {
				fprintf(stderr,"ファイル書き込みに失敗しました。\n");
				free(buf);
				return 1; 
			}
		}
		fclose(fp);
#endif
		endtime=getzikan();
		printf("書き込み時間\n");
		printf("%lldms\n",endtime-starttime);
		printf("書き込み速度\n");
		if(endtime==starttime) {
			printf("速すぎるため計測不能です。\n");
		} else {
			speed=(double)realsize*1000/(double)(endtime-starttime);
			printf("1MB=1024*1024Bとして\n");
			printf("%gMB/S\n",speed/1024/1024);
			printf("1MB=1000*1000Bとして\n");
			printf("%gMB/S\n",speed/1000/1000);
		}
	}
#ifdef USE_DOUBLE_FILE
	/*ファイル名の変更*/
	if(filename2!=NULL) {
		if(rename(filename,filename2)) {
			fprintf(stderr,"ファイルのリネームに失敗しました。\n");
		} else {
			filename=filename2;
		}
	}
#endif
	/*読み込み時間の測定*/
	if(mode!=MODE_WRITE) {
		starttime=getzikan();
#ifdef USE_WIN_FILE_API
#ifdef WIN_FILE_API_BUFFERING
		fp=CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0);
#else
		fp=CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL |
			FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN,0);
#endif
		if(fp==INVALID_HANDLE_VALUE) {
			fprintf(stderr,"ファイルオープンに失敗しました。\n");
			free(buf);
			return 1; 
		}
		for(i=0;i<writenum;i++) {
			if(!ReadFile(fp,buf,bufsize,&win_ac_size,NULL) ||
					win_ac_size!=bufsize) {
				fprintf(stderr,"ファイル読み込みに失敗しました。\n");
				free(buf);
				return 1;
			}
		}
		CloseHandle(fp);
#else
		fp=fopen(filename,"rb");
		if(fp==NULL) {
			fprintf(stderr,"ファイルオープン(読み込み)に失敗しました。\n");
			free(buf);
			return 1; 
		}
		for(i=0;i<writenum;i++) {
			if(fread(buf,bufsize,1,fp)!=1) {
				fprintf(stderr,"ファイル読み込みに失敗しました。\n");
				free(buf);
				return 1; 
			}
		}
		fclose(fp);
#endif
		endtime=getzikan();
		printf("読み込み時間\n");
		printf("%lldms\n",endtime-starttime);
		printf("読み込み速度\n");
		if(endtime==starttime) {
			printf("速すぎるため計測不能です。\n");
		} else {
			speed=(double)realsize*1000/(double)(endtime-starttime);
			printf("1MB=1024*1024Bとして\n");
			printf("%gMB/S\n",speed/1024/1024);
			printf("1MB=1000*1000Bとして\n");
			printf("%gMB/S\n",speed/1000/1000);
		}
	}
	/*ファイルの削除*/
	if(mode==MODE_BOTH) {
		if(remove(filename)) {
			fprintf(stderr,"ファイルの削除に失敗しました。\n");
		}
	}
	/*バッファの開放*/
	free(buf);
	/*正常終了*/
	return 0;
}
実行結果

コード:

F:\C\calcacspeed>calcacspeed -f D:\test.dat
書き込み時間
1388ms
書き込み速度
1MB=1024*1024Bとして
35.8823MB/S
1MB=1000*1000Bとして
37.6254MB/S
読み込み時間
1404ms
読み込み速度
1MB=1024*1024Bとして
35.4734MB/S
1MB=1000*1000Bとして
37.1966MB/S
CrystalDiskMark 3.0.1での結果

コード:

-----------------------------------------------------------------------
CrystalDiskMark 3.0.1 (C) 2007-2010 hiyohiyo
                           Crystal Dew World : http://crystalmark.info/
-----------------------------------------------------------------------
* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

           Sequential Read :    37.975 MB/s
          Sequential Write :    35.954 MB/s
         Random Read 512KB :    19.078 MB/s
        Random Write 512KB :    28.385 MB/s
    Random Read 4KB (QD=1) :     0.343 MB/s [    83.7 IOPS]
   Random Write 4KB (QD=1) :     1.537 MB/s [   375.3 IOPS]
   Random Read 4KB (QD=32) :     0.847 MB/s [   206.7 IOPS]
  Random Write 4KB (QD=32) :     1.333 MB/s [   325.4 IOPS]

  Test : 50 MB [D: 84.6% (101.5/119.9 GB)] (x1)
  Date : 2011/11/20 12:49:37
    OS : Windows Vista Home Premium Edition SP2 [6.0 Build 6002] (x86)
  
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

“C言語何でも質問掲示板” へ戻る