Design and Implementation of SylixOS Memory Performance Testing Program

Posted by TheOracle on Mon, 08 Jul 2019 19:43:02 +0200

1. Memory Performance Test Requirements

        SylixOS, as a large real-time operating system, has important applications in various fields. Among them, in the field of high-performance computing, we need to have an intuitive, cross-platform memory testing software to give the memory performance data of Sylix OS in various platforms.

2. Memory Performance Testing Principle

        Memory performance is no more than the read-write speed of memory access. The test of memory read-write speed needs to record the operation time before and after full-speed memory operation. The operation speed can be obtained according to the operation time and the memory size of the operation. As shown in formula 21, V is the speed of memory operation, S is the capacity of memory operation, and T is the time-consuming of memory operation.

Formula 2-1 Velocity Calculating Formula

3. Design and Implementation of Memory Performance Testing Program

        Considering the need to compare with other operating systems, we try to use general memory operation interface to implement the relevant programs. The flow chart of the test program is shown.

Figure 31 Memory Test Program Flow Chart

3.1. Memory operations

        In the aspect of memory operation, we mainly consider the read and write of memory.

3.1.1 Read Memory

        With regard to read operation, memory pointer can be directly manipulated, and the value of the corresponding location of memory can be directly assigned to the registers, which can achieve higher operational efficiency. In addition, because the cycle in the operation process may lead to excessive time-consuming, some optimization needs to be done.

3.1.2 Write memory

        With regard to write operations, we can directly use the memset function to write all the locations in memory space to 0.

3.1.3 Memory copy

        With regard to memory copy, the memcpy function can be used to test the efficiency of integrated memory copy.

3.2 Timing

        In reading and writing tests, accurate recording of time is very important. Under the conventional POSIX platform, gettimeofday is a precise time acquisition function to microsecond level. Under SylixOS, gettimeofday calls to the high-precision clock of the system, so it is also very precise, so we can use gettimeofday function in the operation of time.

3.3 Output of Result

        Because the memory operation is very fast and the conventional data output is relatively time-consuming, it is necessary to record the memory operation capacity and operation time first, and output the test results when the final processing is completed.

3.4 Implementation

3.4.1 Adjustment of Program Priority

        When the program runs, it needs to adjust the priority to the relatively uninterrupted priority. Here, it is configured as 100. The specific program is shown in the program list 31.

List of procedures 31

struct sched_param   schedParam;int                   iRet;

iRet = sched_getparam(0, &schedParam);            /*Getting process control block information            */if (iRet != 0) {
    perror("sched_getparam");    return -1;
}                                                  /*Set priority to 100              */schedParam.sched_priority = PX_PRIORITY_CONVERT(100);
iRet = sched_setscheduler(0, SCHED_RR, &schedParam);if (iRet != 0) {    return -1;
}

3.4.2 Memory space application and initialization

        Memory space used for memory testing must be continuous physical space, so as to get more accurate test results. calloc function is used here to allocate memory space. The specific function implementation is shown in Listing 3-2 of the program.

Listing 3-2

/**********************************************************************************
** Function name: makeSpace
** Function description: Apply for memory space
** Enter: ullSpace Size
** Output: Applied memory space pointer
** Call module: NONE********************************************************************************************************************************/static long  *pMakeSpace (unsigned long long  ullSpaceSize){    unsigned int        uiLen   = sizeof(long);    unsigned long long  i;    long               *plSpace = NULL;    plSpace = calloc(ullSpaceSize, uiLen);            /* Apply for contiguous memory space           */    if (plSpace == NULL) {                            /* Failure to apply for direct return and withdrawal         */        perror("allocating memory failed!");        exit(1);    }    for (i = 0; i < ullSpaceSize; i++) {              /* Initial value of memory content assignment               */        plSpace[i] = 0xaa;    }    return plSpace;                                   /* Return the memory space pointer of the application       */}

3.4.3 Write test functions

        Writing test function is mainly to use memset function to write 0 continuous space, multiple operations to obtain the operation time. The specific implementation is shown in the program list 33.

Listing 3-3

/**********************************************************************************
** Function name: writebenchMark
** Function Description: Memory Writing Performance Processing
** Enter: ullSpace Size
**           lSpaceDest    Target memory space
** Output: Applied memory space pointer
** Call module: 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);                    /* Get the system time before the copy         */    for (i = 0; i < CPLOOPS; i++) {        memset(plSpaceDest, 0, ullSpaceBytes);       /* Make circular copies                   */    }    gettimeofday(&tmEnd, NULL);                      /* Get the system time after the copy is completed     */    dRet = ((double)(tmEnd.tv_sec * 1000000 -        /* Time-consuming before and after acquisition             */                     tmStart.tv_sec * 1000000 +                     tmEnd.tv_usec -                     tmStart.tv_usec))/1000000;    return dRet;                                      /* Return time-consuming                     */}

3.4.4 Read test functions

        Read test mainly copies all the memory data into the register directly to test. Because the number of loops will also affect the results. Considering some adjustments, the specific implementation is shown in Listing 3-4 of the program.

Listing 3-4

/**********************************************************************************
** Function name: readbenchMark
** Function Description: Memory Read Performance Processing
** Enter: ullSpace Size
**          lSpaceSrc     Source memory space
** Output: Applied memory space pointer
** Call module: 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);                      /* Get the system time before the copy         */

    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);                       /* Get the system time after the copy is completed     */

    dRet = ((double)(tmEnd.tv_sec * 1000000 -         /* Time-consuming before and after acquisition             */
                     tmStart.tv_sec * 1000000 +                     tmEnd.tv_usec -
                     tmStart.tv_usec))/1000000;    return dRet;                                      /* Return time-consuming                     */}

3.4.5 Copy test function

        Copy test function mainly tests the efficiency of memcpy function to copy two memory data. The implementation is shown in Listing 35.

List of procedures 35

/**********************************************************************************
** Function name: cpbenchMark
** Function Description: Memory Copy Performance Processing
** Enter: ullSpace Size
**           lSpaceSrc
**           lSpaceDest
** Output: Applied memory space pointer
** Call module: 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);                       /* Get the system time before the copy         */    for (i = 0; i < CPLOOPS; i++) {    	mempcpy(plSpaceDest, plSpaceSrc, ullSpaceBytes);/* Make circular copies                   */    }    gettimeofday(&tmEnd, NULL);                         /* Get the system time after the copy is completed     */    dRet = ((double)(tmEnd.tv_sec * 1000000 -           /* Time-consuming before and after acquisition             */                     tmStart.tv_sec * 1000000 +                     tmEnd.tv_usec -                     tmStart.tv_usec))/1000000;    return dRet;                                        /* Return time-consuming                     */}

3.4.6 Result output function

        The output function can be completed by using simple printf, which is shown in Listing 36.

Program List 36

/**********************************************************************************
** Function name: reqOut
** Function Description: Output Function of Result
** Input: dTm Copy Time-consuming
**          dSize  Copy content size
** Output: NONE
** Call module: NONE
**********************************************************************************/static void  reqOut (double  dTm, double  dSize, int  iType){    switch (iType) {    case WRITETYPE:        printf("MEMWRITE\t");                          /* Display operation type               */
        break;    case READTYPE:        printf("MEMREAD \t");                          /* Display operation type               */
        break;    case CPTYPE:        printf("MEMCPY  \t");                           /* Display operation type               */
        break;    default:        return ;
    }    printf("CPLOOPS: %d\t", CPLOOPS);                  /* Display the number of copies                 */
    printf("Elapsed: %.5f\t", dTm);                    /* Display copy time-consuming                 */
    printf("MiB: %.5f\t", dSize);                      /* Display copy data size             */
    printf("Handle: %.3f MiB/s\n", 
           dSize/dTm * CPLOOPS);                       /* Display copy rate                 */

    return;
}