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; }