SylixOS 内存性能测试程序设计与实现

1. 内存性能测试需求

        SylixOS作为大型实时操作系统,在各个领域当中都会有重要应用。其中,在高性能运算领域需要较高的内存读写性能,因此我们需要有一个直观,跨平台的内存测试软件来给出SylixOS在各个平台的内存性能数据。

2. 内存性能测试原理

        内存性能无非内存访问的读写速度,内存读写速度的测试需要在全速的内存的操作前后记录操作耗时,根据操作耗时和操作的内存大小得出操作的速度。原理如公式公式 2 1所示,V为内存操作速度,S为内存操作的容量,T为内存操作的耗时。

SylixOS 内存性能测试程序设计与实现_第1张图片

公式 2-1 速度计算公式

3. 内存性能测试程序设计与实现

        由于考虑到需要对比其他操作系统,尽量采用通用的内存操作接口来实现相关程序。测试程序流程图如所示。

SylixOS 内存性能测试程序设计与实现_第2张图片

图 3‑1 内存测试程序流程图

3.1    内存操作

        在内存操作方面,主要考虑到内存的读,写这两种操作。

3.1.1    读内存

        关于读操作,可以直接操作内存指针,将内存对应位置的值直接赋值给寄存器,这样可以达到较高的操作效率,另外由于操作过程中的循环可能导致耗时过多,需要做一些优化。

3.1.2    写内存

        关于写操作,可以直接采用memset函数将内存空间内所有的位置全部写0。

3.1.3    内存拷贝

        关于内存拷贝,可以使用memcpy函数来测试下内存综合拷贝的效率。

3.2      计时

        在读写测试中,对时间的精确记录是非常重要的。在常规的POSIX平台下,gettimeofday是个精确到微秒级别的时间获取函数,在SylixOS下,gettimeofday调用到系统的高精度时钟,所以也是十分精准的,因此我们可以在计时的操作中使用gettimeofday函数。

3.3    结果输出

        由于内存操作是十分快速的,并且常规的数据输出是相对耗时的,所以需要优先记录好内存操作的容量和操作耗时,在最后全部处理完时在进行运算输出测试结果。

3.4      具体实现

3.4.1   程序优先级的调整

        程序运行时需要将优先级调整到相对不会被打断的优先级,这里配置为100,具体程序如程序清单 3‑1所示。

程序清单 3‑1

struct sched_param   schedParam;
int                   iRet;

iRet = sched_getparam(0, &schedParam);            /*获取进程控制块信息            */
if (iRet != 0) {
    perror("sched_getparam");
    return -1;
}
                                                  /*设置优先级为100              */
schedParam.sched_priority = PX_PRIORITY_CONVERT(100);
iRet = sched_setscheduler(0, SCHED_RR, &schedParam);
if (iRet != 0) {
    return -1;
}

3.4.2   内存空间申请并初始化

        用于内存测试的内存空间必须是连续的物理空间,这样才能得到比较精准的测试结果,这里采用的是calloc函数来分配内存空间,具体函数实现如程序清单 3-2所示。

程序清单 3-2

/**********************************************************************************
** 函数名称: makeSpace
** 功能描述: 申请内存空间
** 输    入: ullSpaceSize  要申请空间的大小
** 输    出: 申请到的内存空间指针
** 调用模块: NONE
**********************************************************************************/
static long  *pMakeSpace (unsigned long long  ullSpaceSize)
{
    unsigned int        uiLen   = sizeof(long);
    unsigned long long  i;
    long               *plSpace = NULL;

    plSpace = calloc(ullSpaceSize, uiLen);            /* 申请连续的内存空间           */
    if (plSpace == NULL) {                            /* 申请失败直接返回退出         */
        perror("allocating memory failed!");
        exit(1);
    }

    for (i = 0; i < ullSpaceSize; i++) {              /* 内存内容赋初值               */
        plSpace[i] = 0xaa;
    }

    return plSpace;                                   /* 返回申请的内存空间指针       */
}

3.4.3   写测试函数

        写测试函数主要是使用memset函数将连续的空间写0,多次操作来获取操作的时间。具体实现如程序清单 3‑3所示。

程序清单 3-3

/**********************************************************************************
** 函数名称: writebenchMark
** 功能描述: 内存写性能处理
** 输    入: ullSpaceSize  要申请空间的大小
**           lSpaceDest    目标内存空间
** 输    出: 申请到的内存空间指针
** 调用模块: NONE
**********************************************************************************/
static double  writebenchMark (unsigned long long  ullSpaceSize,
                               long               *plSpaceDest)
{
    struct timeval      tmStart;
    struct timeval      tmEnd;
    unsigned int        uiLen         = sizeof(long);
    unsigned long long  ullSpaceBytes = ullSpaceSize * uiLen;
    int                 i;
    double              dRet = 0;

    gettimeofday(&tmStart, NULL);                    /* 获取拷贝前的系统时间         */

    for (i = 0; i < CPLOOPS; i++) {
        memset(plSpaceDest, 0, ullSpaceBytes);       /* 做循环拷贝                   */
    }

    gettimeofday(&tmEnd, NULL);                      /* 获取拷贝完成后的系统时间     */

    dRet = ((double)(tmEnd.tv_sec * 1000000 -        /* 获取前后耗时时间             */
                     tmStart.tv_sec * 1000000 +
                     tmEnd.tv_usec -
                     tmStart.tv_usec))/1000000;

    return dRet;                                      /* 返回耗时                     */
}

3.4.4   读测试函数

        读测试主要直接将内存数据全部复制到寄存器中的操作来测试的,其中由于循环的次数较多也会影响结果,顾做了一些调整,具体实现如程序清单 3-4所示。

程序清单 3-4

/**********************************************************************************
** 函数名称: readbenchMark
** 功能描述: 内存读性能处理
** 输    入: ullSpaceSize  要申请空间的大小
**          lSpaceSrc     源内存空间
** 输    出: 申请到的内存空间指针
** 调用模块: NONE
**********************************************************************************/
static double  readbenchMark (unsigned long long   ullSpaceSize,
                              long                *plSpaceSrc)
{
    struct timeval      tmStart;
    struct timeval      tmEnd;
    unsigned long long  ullCouont     = 0;
    int                 i;
    double              dRet          = 0;
    register long       lReader       = 0;
    long               *plSpaceSrcTmp = NULL;

    dRet = lReader;
    gettimeofday(&tmStart, NULL);                      /* 获取拷贝前的系统时间         */

    for (i = 0; i < CPLOOPS; i++) {
        plSpaceSrcTmp = plSpaceSrc;
        for (ullCouont = 0; ullCouont < ullSpaceSize; ullCouont +=64 ) {
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
            lReader = *plSpaceSrcTmp++;
        }
    }

    gettimeofday(&tmEnd, NULL);                       /* 获取拷贝完成后的系统时间     */

    dRet = ((double)(tmEnd.tv_sec * 1000000 -         /* 获取前后耗时时间             */
                     tmStart.tv_sec * 1000000 +
                     tmEnd.tv_usec -
                     tmStart.tv_usec))/1000000;

    return dRet;                                      /* 返回耗时                     */
}

3.4.5    拷贝测试函数

        拷贝测试函数主要测试memcpy函数拷贝两个内存数据的效率。具体实现如程序清单 3‑5所示

程序清单 3‑5

/**********************************************************************************
** 函数名称: cpbenchMark
** 功能描述: 内存拷贝性能处理
** 输    入: ullSpaceSize  要申请空间的大小
**           lSpaceSrc
**           lSpaceDest
** 输    出: 申请到的内存空间指针
** 调用模块: NONE
**********************************************************************************/
static double  cpbenchMark (unsigned long long    ullSpaceSize,
                            long                 *plSpaceSrc,
                            long                 *plSpaceDest)
{
    struct timeval      tmStart;
    struct timeval      tmEnd;
    unsigned int        uiLen         = sizeof(long);
    unsigned long long  ullSpaceBytes = ullSpaceSize * uiLen;
    int                 i;
    double              dRet = 0;

    gettimeofday(&tmStart, NULL);                       /* 获取拷贝前的系统时间         */

    for (i = 0; i < CPLOOPS; i++) {
    	mempcpy(plSpaceDest, plSpaceSrc, ullSpaceBytes);/* 做循环拷贝                   */
    }

    gettimeofday(&tmEnd, NULL);                         /* 获取拷贝完成后的系统时间     */

    dRet = ((double)(tmEnd.tv_sec * 1000000 -           /* 获取前后耗时时间             */
                     tmStart.tv_sec * 1000000 +
                     tmEnd.tv_usec -
                     tmStart.tv_usec))/1000000;

    return dRet;                                        /* 返回耗时                     */
}

3.4.6   结果输出函数

        使用简单的printf即可完成输出函数,具体实现如程序清单 3‑6所示。

程序清单 3‑6

/**********************************************************************************
** 函数名称: reqOut
** 功能描述: 结果输出函数
** 输    入: dTm    拷贝耗时
**          dSize  拷贝内容大小
** 输    出: NONE
** 调用模块:  NONE
**********************************************************************************/
static void  reqOut (double  dTm, double  dSize, int  iType)
{
    switch (iType) {
    case WRITETYPE:
        printf("MEMWRITE\t");                          /* 显示操作类型               */
        break;

    case READTYPE:
        printf("MEMREAD \t");                          /* 显示操作类型               */
        break;

    case CPTYPE:
        printf("MEMCPY  \t");                           /* 显示操作类型               */
        break;

    default:
        return ;
    }

    printf("CPLOOPS: %d\t", CPLOOPS);                  /* 显示拷贝次数                 */
    printf("Elapsed: %.5f\t", dTm);                    /* 显示拷贝耗时                 */
    printf("MiB: %.5f\t", dSize);                      /* 显示拷贝数据大小             */
    printf("Handle: %.3f MiB/s\n", 
           dSize/dTm * CPLOOPS);                       /* 显示拷贝速率                 */

    return;
}

 

转载于:https://my.oschina.net/senjienly/blog/880667

你可能感兴趣的:(SylixOS 内存性能测试程序设计与实现)