1、分布式软件测试工具IOR源代码结构分析一、程序的功能IOR是测试基准程序,它的功能是接受参数,在client上产生特定的负载,测试系统的系能,并输出测试结果。根据IOR的功能,可以把IOR程序分成三个模块:词法分析模块、负载模块、底层函数模块。 输入的参数有三种形式:选项形式-比如 “-w r f c Z” 等赋值形式,在-O选项后面赋值,比如“ O api=POSIX”配置脚本形式,在配置脚本中,给参数结构体IOR_param_t成员赋值,形式如 “f script.txt”使用配置脚本形式,可以设置几次测试,每次测试的参数都不一样。 IOR能模拟不同的负载,所以负载模块很复杂,其中最重要的
2、函数TestIoSys()有400+行代码。在TestIoSys()有许多条件语句,根据参数结构体IOR_param_t里成员的值,产生不同操作。修改IOR,减少不必要的参数,增加读写比例参数,就需要修改结构体IOR_param_t,和修改TestIoSys()函数。二、程序的主要流程简略分析main函数流程,下面是main函数的不完全代码:int main(int argc, char * argv) IOR_queue_t * tests; /*IOR_queue_t是参数结构体IOR_param_t的链表结构*/ tests = SetupTests(argc,argv); /*接受参数
3、设置,并检查参数,然后填充参数结构体*/ While(tests != NULL) TestIoSys(&tests-testParameters); /*根据参数结构体的成员,进行测试*/ test = test-nextTest; /*下一个测试*/ ParseCommandLine /词法分析命令参数,并填充参数结构体DistributeHints /把环境变量分发到各个进程VaildTests /检查各个参数结构体内的参数是否有效TimeDeviation /检查每个任务之间开始时间的偏差SeedRandGen /产生随机数ShowTest /显示参数信息AioriBind /装填I/
4、O接口ShowSetup /显示设置信息SummarizeResults /显示测试结果Time0 /定时器伪代码ReduceIterResults /归约操作,计算结果三、程序的主要数据结构两个重要的数据结构是:aiori.h中定义的参数结构体IOR_param_t。用来填充参数。IOR.h中定义的参数结构体队列IOR_queue_t。运行一次程序可以执行几次参数不同的测试。typedef struct char debugMAX_STR; /* debug info string */ unsigned int mode; /* file permissions */ unsigned i
5、nt openFlags; /* open flags */ int TestNum; /* test reference number */ char apiMAX_STR; /* API for I/O */ int numTasks; /* number of tasks for test */ int nodes; /* number of nodes for test */ int tasksPerNode; /* number of tasks per node */ int repetitions; /* number of repetitions of test */ . in
6、t readFile; /* read of existing file */ int writeFile; /* write of file */ . int keepFile; /* dont delete the testfile on exit */./* POSIX variables */int singleXferAttempt; /* do not retry transfer if incomplete */int fsYncPerWrite; /* fsync() after each write */int fsync; /* fsync() after write */
7、* MPI variables */MPI_Datatype transferType; /* datatype for transfer */MPI_Datatype fileType; /* filetype for file view */* HDF5 variables */int individualDataSets; /* datasets not shared by all procs */int noFill; /* no fill in file creation */IOR_offset_t setAlignment; /* alignment in bytes */* N
8、CMPI variables */int var_id; /* variable id handle for data set */* Lustre variables */int lustre_stripe_count;int lustre_stripe_size;int lustre_start_ost;int lustre_ignore_locks; IOR_param_t;typedef struct IOR_queue_t IOR_param_t testParameters; struct IOR_queue_t * nextTest; IOR_queue_t;四、程序的模块4.1
9、 词法分析模块该模块包含的C文件有 Parse_options.c该文件包括defaults.h头文件,defaults.h头文件是一个参数结构体defaultParameters的定义,该结构体包含默认的参数值。Parse_options.c包含5个主要函数,如下表所示。函数名功能ParseCommandLine对命令行参数进行词法分析ParseLine对一行字符串调用DecodeDirective函数进行词法分析ReadConfigScript读取配置脚本,分配并填充参数结构体DecodeDirective分析诸如“transferSize=64k”一样的偶对,并给参数结构体中的trans
10、ferSize赋值。CheckRunSettings检查和纠正每次测试参数的参数值。1.参数结构体中的writeFile、readFile、checkWrite、checkRead值为FALSE时,设置readFile和writeFile的值为TRUE。2.当参数结构体中的numTasks为0时,设置numTasks=MPI进程数 ParseCommandLine函数是词法分析模块的最主要的函数,它和其他函数的关系如下图 小结:参数的输入形式有三种,但对于我们编写的聚合带宽程序只需要一种输入形式,即命令行形式。所以我们只使用ParseCommandLine函数,其他函数可以删除。4.2 负载模
11、块 该模块包含的C文件有 IOR.C utilities.c IOR.C文件中有主函数main,SetupTests函数,TestIOSys函数,WriteOrRead函数 负载模块的函数关系图如下:4.2.1 参数介绍编号参数参数作用描述所对应的参数结构体成员成员类型默认值重要程度1-A # 测试标志,可以在输出结果上显示,作为标记。test reference number for easier test identification in log filesTestNum数值-12-a POSIX|MPIIOAPI接口选项api字符串POSIX重要3-b #数据块大小blockSize数
12、值1048576重要4-B用于POSIX接口,使用直接I/O,不使用I/O缓存。useO_DIRECT布尔0一般5-c聚合(collective)I/O,MPI的文件操作为组调用collective布尔0一般6-C读操作时,读取其他任务所写的文件。所有任务的任务偏移量是常量。reorderTasks布尔0一般7-Q #任务偏移量,用于-C Z选项taskPerNodeOffset数值1一般8-Z所有任务的任务偏移量不是常量,是随机产生的。reorderTasksRandom布尔0一般9-X #与-Z选项一起使用。当0时,每次循环的随机种子都一样,当numTasks任务所写的文件。以下代码是Te
13、stIoSys函数中的部分代码,作用是产生任务偏移值/*读文件,并在每次I/O操作间计时。*/if (test-readFile & (maxTimeDuration ? (GetTimeStamp() - startTime reorderTasks) rankOffset = (test-taskPerNodeOffset*test-tasksPerNode) % test-numTasks; /* 当设置-Z Q (-X)选项时,产生的任务偏移值是随机的*/if (test-reorderTasksRandom) /*以下操作不会与文件偏移值(-Z选项)冲突,因为GetOffsetArr
14、ayRandom函数产生文件偏移值 */int *rankoffs, *filecont, *filehits, ifile, jfile, nodeoffset;unsigned int iseed0;nodeoffset = test-taskPerNodeOffset;nodeoffset = (nodeoffset nodes) ? nodeoffset : test-nodes-1;iseed0= (test-reorderTasksRandomSeed reorderTasksRandomSeed+rep):test-reorderTasksRandomSeed; srand(ra
15、nk+iseed0); rankOffset = rand() % test-numTasks; while (rankOffset tasksPerNode) rankOffset = rand() % test-numTasks; 4.2.5 测试文件的命名 每个任务调用GetTestFileName函数就能得到测试文件的文件名。测试文件的文件名与参数结构体变量中成员(filePerProc、uniqueDir、multiFile、repCounter)有关。 以下是GetTestFileName的源代码:void GetTestFileName(char * testFileName,
16、IOR_param_t * test) char * fileNames, initialTestFileNameMAXPATHLEN, testFileNameRootMAX_STR, tmpStringMAX_STR; int count; strcpy(initialTestFileName, test-testFileName); fileNames = ParseFileName(initialTestFileName, &count); /*1*/ if (count 1 & test-uniqueDir = TRUE) /*2*/ ERR(cannot use multiple
17、file names with unique directories);if (test-filePerProc) /*3*/ strcpy(testFileNameRoot, fileNames(rank+rankOffset)%test-numTasks) % count); /*4*/else strcpy(testFileNameRoot, fileNames0); /*5*/ /* give unique name if using multiple files */if (test-filePerProc) /*6*/ /* prepend rank subdirectory be
18、fore filename, e.g., /dir/file = /dir/file*/ if (test-uniqueDir = TRUE) /*7*/ strcpy(testFileNameRoot, PrependDir(test, testFileNameRoot); /*8*/ sprintf(testFileName, %s.%08d, testFileNameRoot, (rank+rankOffset)%test-numTasks); /*9*/ else strcpy(testFileName, testFileNameRoot); /*10*/ /* add suffix
19、for multiple files */if (test-repCounter -1) /*11*/ sprintf(tmpString, .%d, test-repCounter); strcat(testFileName, tmpString); /*12*/ /* GetTestFileName() */ 为了便于分析,我们设num=(rank+rankOffset)%test-numTasks。在第1行中,ParseFileName函数对参数结构体中成员testFileName进行词法分析,比如当testFileName=”/tmp/myfs/mnt/testfs/mnt/nfs”时,fileNames0=” /tmp/myfs”, fileNames1=” /mnt/testfs”, fileNames2=” /mnt/nfs”。第8行中,PrependDir函数能把”/mnt/testfs”变成”/mnt/testfs”。第11行中,当设置-m选项时,即参数结构体成员multiFile被设置为1时,给测试文件名加上后缀,后缀是循环序号。当count=1时,testFileName=
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1