SylixOS 內存性能測試程序設計與實現

1. 內存性能測試需求

        SylixOS作爲大型實時操作系統,在各個領域當中都會有重要應用。其中,在高性能運算領域需要較高的內存讀寫性能,因此我們需要有一個直觀,跨平臺的內存測試軟件來給出SylixOS在各個平臺的內存性能數據。

2. 內存性能測試原理

        內存性能無非內存訪問的讀寫速度,內存讀寫速度的測試需要在全速的內存的操作前後記錄操作耗時,根據操作耗時和操作的內存大小得出操作的速度。原理如公式公式 2 1所示,V爲內存操作速度,S爲內存操作的容量,T爲內存操作的耗時。

公式 2-1 速度計算公式

3. 內存性能測試程序設計與實現

        由於考慮到需要對比其他操作系統,儘量採用通用的內存操作接口來實現相關程序。測試程序流程圖如所示。

圖 31 內存測試程序流程圖

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,具體程序如程序清單 31所示。

程序清單 31

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,多次操作來獲取操作的時間。具體實現如程序清單 33所示。

程序清單 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函數拷貝兩個內存數據的效率。具體實現如程序清單 35所示

程序清單 35

/**********************************************************************************
** 函數名稱: 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即可完成輸出函數,具體實現如程序清單 36所示。

程序清單 36

/**********************************************************************************
** 函數名稱: 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;
}

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章