iometer 1.1.0 版本包含了3种Write IO Data Pattern。分别是:Repeating bytes、Pseudo-Random (2006.07.27及其之前的版本默认) 和 Full random。实际上这三种IO数据类型的代码在1.1.0 rc1 就已经合入。
-------------------
Version 1.1.0 (RC1)
===================
- New features:
- (All) Different data randomization options are now available via a drop down menu in the GUI. Options are: "Repeating bytes","Pseudo-Random" (used by version 2006.07.27 and older) and "Full random".
- (All) Randomization seeding support (by Ryan Bever) was added to define a fixed seed for the random number generator. A fixed seed can be specified on a per Manager or per Worker basis in the Disk Targets page of the GUI.
..........(省略多字,详细内容将查阅:http://sourceforge.net/p/iometer/svn/HEAD/tree/trunk/IOmeter/CHANGELOG.txt)
-------------------
IOTargetDisk.cpp 文件:
//
// Logical drives are accessed through a file on the drive. This will create
// the file by writing in units of "bytes" beginning at "*prepare_offset". It
// maintains a simple I/O queue of depth PREPARE_QDEPTH, which it keeps as
// full as possible. It keeps queueing up new I/Os until the disk fills up,
// or the user-specified file size (starting_sector + maximum_size) is reached,
// or a STOP_PREPARE message is received (reflected in "*test_state"). It
// returns only when all queued I/Os have completed.
// Return value is TRUE for success, FALSE if any error occurred.
//
BOOL TargetDisk::Prepare(DWORDLONG * prepare_offset, volatile TestState * test_state, int sector_size, unsigned char* _random_data_buffer, long long _random_datat_buffer_size)
{
BOOL write_ok;
int num_outstanding;
DWORD bytes_written;
OVERLAPPED olap[PREPARE_QDEPTH];
BOOL busy[PREPARE_QDEPTH];
BOOL retval;
int i;
void *buffer = NULL;
DWORD bytes; // static to aid switch to single sectors to finish up preparing
BOOL OnSingleSectors= FALSE; // mark if a switch needs to be made to single sector writes
BOOL singleSectorSwitch = FALSE; // mark that single sectors are being used to write
DWORDLONG rand_seed;
#ifdef IOMTR_SETTING_LINUX_LIBAIO
struct statfs fsInfo;
int statResult;
int fd = -1;
fd = ((struct File *)disk_file)->fd;
#endif
// Save current spec.random so that it can be reset back to the same seed value after preparing disks
// This allows the PRNG to be the same when doing the actual IO, whether the disk is prepped or not and the user specifies fixed seed
rand_seed = spec.random;
// Allocate a large (64k for 512 byte sector size) buffer for the preparation.
bytes = sector_size * 128;
#if defined(IOMTR_OSFAMILY_NETWARE)
NXMemFree(buffer);
errno = 0;
if (!(buffer = NXMemAlloc(bytes, 1)))
#elif defined(IOMTR_OSFAMILY_UNIX)
free(buffer);
errno = 0;
if (!(buffer = valloc(bytes)))
#elif defined(IOMTR_OSFAMILY_WINDOWS)
VirtualFree(buffer, 0, MEM_RELEASE);
if (!(buffer = VirtualAlloc(NULL, bytes, MEM_COMMIT, PAGE_READWRITE)))
#else
#warning ===> WARNING: You have to do some coding here to get the port done!
#endif
{
cout <<"*** Could not allocate buffer to prepare disk." < return FALSE;
}
switch (spec.DataPattern) {
case DATA_PATTERN_REPEATING_BYTES:
// Do nothing here...a new random byte will be chosen below for each IO
break;
case DATA_PATTERN_PSEUDO_RANDOM:
for( DWORD x = 0; x ((unsigned char*)buffer)[x] = (unsigned char)Rand(0xff);
break;
case DATA_PATTERN_FULL_RANDOM:
//Nothing to do here
break;
}
..................
#ifdef IOMTR_SETTING_LINUX_LIBAIO
statResult = fstatfs(fd, &fsInfo);
if (statResult <0) {
cerr <<__FUNCTION__ <<": Couldn‘t statfs logical disk file!" < }
if (fsInfo.f_bfree <= 0 ) {
write_ok = FALSE;
break;
}
#endif
// If we are still writing and the slot is not busy, start an I/O for
// this slot.
if ((*test_state == TestPreparing) && write_ok && !busy[i]) {
// Set its address.
olap[i].Offset = (DWORD) * prepare_offset;
olap[i].OffsetHigh = (DWORD) (*prepare_offset >> 32);
// Fill the buffer with some new random data so we aren‘t writing all zeros each time
switch (spec.DataPattern) {
case DATA_PATTERN_REPEATING_BYTES:
memset(buffer, rand(), bytes);
break;
case DATA_PATTERN_PSEUDO_RANDOM:
break; // Nothing to do here, buffer was set above
case DATA_PATTERN_FULL_RANDOM:
//Buffer offset must be DWORD-aligned in memory, otherwise the transfer fails
//Choose a pointer into the buffer
long long mem_offset = (long long)Rand(_random_datat_buffer_size-bytes);
//See how far it is from being DWORD-aligned
long long remainder = mem_offset & (sizeof(DWORD) - 1);
//Align the pointer using the remainder
mem_offset = mem_offset - remainder;
buffer = &_random_data_buffer[mem_offset];
break;
}
// Do the asynchronous write.
if (WriteFile(disk_file, (char *)buffer, bytes, &bytes_written, &(olap[i]))) {
// It succeeded immediately!
#ifdef _DEBUG
cout <<"Wrote (immediately) " < <#endif
// Advance the file pointer, but do not mark the slot as busy.
*prepare_offset += bytes;
} else {
// It did not succeed immediately... did it start OK?
if (GetLastError() == ERROR_IO_PENDING) {
// It started OK.
#if _DETAILS
cout <<"I/O started successfully for slot #" < <<" for " < <<*prepare_offset <#endif
---------------
Repeating bytes:
Pseudo-Random:
Full random:
目前我知道的一个领域情况是,iometer 选择不同IO Data Pattern,可以用于数据压缩算法产品的测试结果的效果宣传上。存储领域,我想近几年的数据重删应用,可能偶尔会用到这些。对比三种方式,可以看出,采用Repeating bytes 方式,是最利于产品宣传的。而iometer 2006.07.27 版本默认是伪随机方式,故,最好采用iometer 1.1.0 GA 版本,或者基于这个版本的增强版本(笔者博客目前有一个20150123A1版本)。
本文出自 “Gedankenwesen” 博客,请务必保留此出处http://yungchin.blog.51cto.com/9614170/1609825
iometer 1.1.0 重要特性说明之Write IO Data Pattern