猫太的鱼 发表于 2013-1-26 14:25:00

测试进程上下文切换时间

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


测试程序(1) 使用gettimeofday()获取当前时间
--------------------------------------------------
#include <stdio.h>#include <stdlib.h>#include <sys/time.h>#include <time.h>#include <sched.h>#include <sys/types.h>#include <unistd.h>      //pipe()int main(){    int x, i, fd, p;    char send    = 's';    char receive;    pipe(fd);    pipe(p);    struct timeval tv;    struct sched_param param;    param.sched_priority = 0;    while ((x = fork()) == -1);    if (x==0) {      sched_setscheduler(getpid(), SCHED_FIFO, &param);      gettimeofday(&tv, NULL);      printf("Before Context Switch Time %u us\n", tv.tv_usec);      for (i = 0; i < 10000; i++) {            read(fd, &receive, 1);            write(p, &send, 1);      }      exit(0);    }    else {      sched_setscheduler(getpid(), SCHED_FIFO, &param);      for (i = 0; i < 10000; i++) {            write(fd, &send, 1);            read(p, &receive, 1);      }      gettimeofday(&tv, NULL);      printf("After Context SWitch Time %u us\n", tv.tv_usec);    }    return 0;}


测试结果(进程切换时间不超过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()获取当前时间
--------------------------------------------------
#include <stdio.h>#include <stdlib.h>#include <sched.h>#include <sys/types.h>#include <unistd.h>long long rdtsc(){    __asm("rdtsc");}int main(){    int x, i, fd, p;    char send    = 's';    char receive;    pipe(fd);    pipe(p);    struct sched_param param;    param.sched_priority = 0;    while ((x = fork()) == -1);    if (x==0) {      sched_setscheduler(getpid(), SCHED_FIFO, &param);      printf("Before Context Switch Time %lld\n", rdtsc());      for (i = 0; i < 10000; i++) {            read(fd, &receive, 1);            write(p, &send, 1);      }      exit(0);    }    else {      sched_setscheduler(getpid(), SCHED_FIFO, &param);      for (i = 0; i < 10000; i++) {            write(fd, &send, 1);            read(p, &receive, 1);      }      printf("After Context Switch Time %lld\n", rdtsc());    }    return 0;}

测试结果(进程切换时间不超过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) 可直接获得进程上下文切换时间
--------------------------------------------------
#include <stdio.h>#include <stdlib.h>      //drand48()#include <sched.h>#include <sys/types.h>#include <unistd.h>#include <sys/time.h>      //gettimeofday()#include <time.h>typedef unsigned long long u64;double clockCycleTimeS,clockRateHZ;/* 获取当前时间,返回秒 */double second() {    struct timeval tv;    gettimeofday(&tv,0);    return tv.tv_sec + 1e-6 * tv.tv_usec;}/* 获取当前时间,返回clock cycle */u64 rdtsc() {    u64 tsc;    __asm__ __volatile__("rdtsc" : "=A" (tsc));    return tsc;}/* 睡眠us微秒 */void selectsleep(unsigned us) {    struct timeval tv;    tv.tv_sec = 0;    tv.tv_usec = us;    select(0, 0, 0, 0, &tv);}/* 计算当前CPU的工作频率 */void calibrate() {    double sumx = 0;    double sumy = 0;    double sumxx = 0;    double sumxy = 0;    double slope;    const unsigned n = 30;    unsigned i;    for (i=0; i<n; i++) {      double breal,real,ticks;      u64 bticks;      breal = second();      bticks = rdtsc();      selectsleep((unsigned)(10000 + drand48() * 200000));      ticks = rdtsc() - bticks;      real = second() - breal;      sumx += real;      sumxx += real * real;      sumxy += real * ticks;      sumy += ticks;    }    slope = ( (sumxy - (sumx*sumy) / n) /            (sumxx - (sumx*sumx) / n) );    clockRateHZ = slope;    clockCycleTimeS = 1.0 / slope;    printf("%3.3f MHz\n", clockRateHZ*1e-6);}int main(){    calibrate();    int x, i, p1, p2, time;    char send    = 's';    char receive;    u64 old_time;    pipe(p1);    pipe(p2);    pipe(time);    struct sched_param param;       param.sched_priority = 0;       while ((x = fork()) == -1);    if (x==0)    {      sched_setscheduler(getpid(), SCHED_FIFO, &param);      old_time = rdtsc();      write(time, &old_time, sizeof(old_time));      for (i = 0; i < 10000; i++) {            read(p1, &receive, 1);            write(p2, &send, 1);      }      exit(0);    }    else    {      u64 new_time;      sched_setscheduler(getpid(), SCHED_FIFO, &param);      for (i = 0; i < 10000; i++) {            write(p1, &send, 1);            read(p2, &receive, 1);      }      new_time = rdtsc();      read(time, &old_time, sizeof(old_time));      printf("Latency time = %3.3f us\n",                1e6 * (new_time - old_time) * clockCycleTimeS / 20000);    }    return 0;}



测试结果(Linux-2.6.21 + RealTime Patch)
--------------------------------------------------
2801.226 MHz
Latency time = 8.129 us
页: [1]
查看完整版本: 测试进程上下文切换时间