测试进程上下文切换时间

测试Context Switch time(进程上下文切换时间) 
-------------------------------------------------- 
    创建两个进程(实时进程)并在它们之间传送一个令牌,如此往返传送一定的次数。其中一个进程在读取令牌时就会引起阻塞。另一个进程发送令牌后等待其返回时也处于阻塞状态。发送令牌带来的开销与上下文切换带来的开销相比,可以忽略不计。 (利用管道传递令牌) 


测试程序(1) 使用gettimeofday()获取当前时间 
--------------------------------------------------
 
C代码    收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sys/time.h>  
  4. #include <time.h>  
  5. #include <sched.h>  
  6. #include <sys/types.h>  
  7. #include <unistd.h>      //pipe()  
  8.   
  9. int main()  
  10. {  
  11.     int x, i, fd[2], p[2];  
  12.     char send    = 's';  
  13.     char receive;  
  14.     pipe(fd);  
  15.     pipe(p);  
  16.     struct timeval tv;  
  17.     struct sched_param param;  
  18.     param.sched_priority = 0;  
  19.   
  20.     while ((x = fork()) == -1);  
  21.     if (x==0) {  
  22.         sched_setscheduler(getpid(), SCHED_FIFO, &param);  
  23.         gettimeofday(&tv, NULL);  
  24.         printf("Before Context Switch Time %u us\n", tv.tv_usec);  
  25.         for (i = 0; i < 10000; i++) {  
  26.             read(fd[0], &receive, 1);  
  27.             write(p[1], &send, 1);  
  28.         }  
  29.         exit(0);  
  30.     }  
  31.     else {  
  32.         sched_setscheduler(getpid(), SCHED_FIFO, &param);  
  33.         for (i = 0; i < 10000; i++) {  
  34.             write(fd[1], &send, 1);  
  35.             read(p[0], &receive, 1);  
  36.         }  
  37.         gettimeofday(&tv, NULL);  
  38.         printf("After Context SWitch Time %u us\n", tv.tv_usec);  
  39.     }  
  40.     return 0;  
  41. }  



测试结果(进程切换时间不超过5us) 
-------------------------------------------------- 
Before Context Switch Time 617087 us 
After Context SWitch Time 702420 us 

702420us - 617087us = 85333 us 
85333us / 20000    = 4.26665 us 

进程切换时间为4.26665 us 

注: cpu MHz         : 2801.042 






测试程序(2) 使用rdtsc()获取当前时间 
--------------------------------------------------
 
C代码    收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <sched.h>  
  4. #include <sys/types.h>  
  5. #include <unistd.h>  
  6.   
  7. long long rdtsc()  
  8. {  
  9.     __asm("rdtsc");  
  10. }  
  11.   
  12. int main()  
  13. {  
  14.     int x, i, fd[2], p[2];  
  15.     char send    = 's';  
  16.     char receive;  
  17.     pipe(fd);  
  18.     pipe(p);  
  19.     struct sched_param param;  
  20.     param.sched_priority = 0;  
  21.   
  22.     while ((x = fork()) == -1);  
  23.     if (x==0) {  
  24.         sched_setscheduler(getpid(), SCHED_FIFO, &param);  
  25.         printf("Before Context Switch Time %lld\n", rdtsc());  
  26.         for (i = 0; i < 10000; i++) {  
  27.             read(fd[0], &receive, 1);  
  28.             write(p[1], &send, 1);  
  29.         }  
  30.         exit(0);  
  31.     }  
  32.     else {  
  33.         sched_setscheduler(getpid(), SCHED_FIFO, &param);  
  34.         for (i = 0; i < 10000; i++) {  
  35.             write(fd[1], &send, 1);  
  36.             read(p[0], &receive, 1);  
  37.         }  
  38.         printf("After Context Switch Time %lld\n", rdtsc());  
  39.     }  
  40.     return 0;  
  41. }  


测试结果(进程切换时间不超过5us) 
-------------------------------------------------- 
Before Context Switch Time 16208184381648 
After Context Switch Time 16208424333213 

16208424333213 - 16208184381648 = 239951565(clock cycle) 
239951565      * 0.357009998 ns = 85665107.74074687 ns 
85665107.74074687 ns / 20000    = 4283.255387037 ns = 4.283255387037 us 






注: cpu MHz         : 2801.042 
--------------------------------------------- 
2 801 042 000Hz 
clock cycle = 1 000 000 000 ns / 2 801 042 000 = 0.357009998ns 

查看CPU性能参数 
cat /proc/cpuinfo
 








测试程序(3) 可直接获得进程上下文切换时间 
--------------------------------------------------
 
C代码    收藏代码
  1. #include <stdio.h>  
  2. #include <stdlib.h>        //drand48()  
  3. #include <sched.h>  
  4. #include <sys/types.h>  
  5. #include <unistd.h>  
  6. #include <sys/time.h>      //gettimeofday()  
  7. #include <time.h>  
  8.   
  9.   
  10. typedef unsigned long long u64;  
  11. double clockCycleTimeS,clockRateHZ;  
  12.   
  13. /* 获取当前时间,返回秒 */  
  14. double second() {  
  15.     struct timeval tv;  
  16.     gettimeofday(&tv,0);  
  17.     return tv.tv_sec + 1e-6 * tv.tv_usec;  
  18. }  
  19.   
  20. /* 获取当前时间,返回clock cycle */  
  21. u64 rdtsc() {  
  22.     u64 tsc;  
  23.     __asm__ __volatile__("rdtsc" : "=A" (tsc));  
  24.     return tsc;  
  25. }  
  26.   
  27. /* 睡眠us微秒 */  
  28. void selectsleep(unsigned us) {  
  29.     struct timeval tv;  
  30.     tv.tv_sec = 0;  
  31.     tv.tv_usec = us;  
  32.     select(0, 0, 0, 0, &tv);  
  33. }  
  34.   
  35. /* 计算当前CPU的工作频率 */  
  36. void calibrate() {  
  37.     double sumx = 0;  
  38.     double sumy = 0;  
  39.     double sumxx = 0;  
  40.     double sumxy = 0;  
  41.     double slope;  
  42.     const unsigned n = 30;  
  43.     unsigned i;  
  44.   
  45.     for (i=0; i<n; i++) {  
  46.         double breal,real,ticks;  
  47.         u64 bticks;  
  48.   
  49.         breal = second();  
  50.         bticks = rdtsc();  
  51.         selectsleep((unsigned)(10000 + drand48() * 200000));  
  52.         ticks = rdtsc() - bticks;  
  53.         real = second() - breal;  
  54.   
  55.         sumx += real;  
  56.         sumxx += real * real;  
  57.         sumxy += real * ticks;  
  58.         sumy += ticks;  
  59.     }  
  60.     slope = ( (sumxy - (sumx*sumy) / n) /  
  61.               (sumxx - (sumx*sumx) / n) );  
  62.     clockRateHZ = slope;  
  63.     clockCycleTimeS = 1.0 / slope;  
  64.     printf("%3.3f MHz\n", clockRateHZ*1e-6);  
  65. }  
  66.   
  67. int main()  
  68. {  
  69.     calibrate();  
  70.   
  71.     int x, i, p1[2], p2[2], time[2];  
  72.     char send    = 's';  
  73.     char receive;  
  74.     u64 old_time;  
  75.     pipe(p1);  
  76.     pipe(p2);  
  77.     pipe(time);  
  78.     struct sched_param param;     
  79.     param.sched_priority = 0;     
  80.   
  81.     while ((x = fork()) == -1);  
  82.     if (x==0)  
  83.     {  
  84.         sched_setscheduler(getpid(), SCHED_FIFO, &param);  
  85.         old_time = rdtsc();  
  86.         write(time[1], &old_time, sizeof(old_time));  
  87.         for (i = 0; i < 10000; i++) {  
  88.             read(p1[0], &receive, 1);  
  89.             write(p2[1], &send, 1);  
  90.         }  
  91.         exit(0);  
  92.     }  
  93.     else  
  94.     {  
  95.         u64 new_time;  
  96.         sched_setscheduler(getpid(), SCHED_FIFO, &param);  
  97.         for (i = 0; i < 10000; i++) {  
  98.             write(p1[1], &send, 1);  
  99.             read(p2[0], &receive, 1);  
  100.         }  
  101.         new_time = rdtsc();  
  102.         read(time[0], &old_time, sizeof(old_time));  
  103.         printf("Latency time = %3.3f us\n",  
  104.                 1e6 * (new_time - old_time) * clockCycleTimeS / 20000);  
  105.     }  
  106.     return 0;  
  107. }  




测试结果(Linux-2.6.21 + RealTime Patch) 
-------------------------------------------------- 
2801.226 MHz 
Latency time = 8.129 us



原文连接:http://ocelot1985-163-com.iteye.com/blog/1029949

转载于:https://my.oschina.net/u/250130/blog/119888

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值