[펌] sleep에 얽힌 이야기들 C / C++

From : http://chonga.pe.kr/computer/programming/sleep_story.txt

[sleep에 얽힌 이야기들]

작성: 이홍기(orinmir _at_ chonga _dot_ pe _dot_ kr; chonga@isoniconline.com)

작성일: 2001년 7월 31일

1. 개요

   세상에는 sleep, usleep, nanosleep, select sleep,

   그리고 assembly clock 소모성 sleep이 존재한다.


2. 특징

   sleep은 1초 단위 이상의 sleeping을 지원하며, thread에서는 안전하지 못하다.

   usleep은 BSD 파생, nanosleep은 POSIX 표준이다. 

   select sleep은 좀더 유연한 플래폼 확장성을 가진다. (Windows 플래폼 제외)

   하지만 select를 이용한 sleep은 다른 sleep들에 비해 cpu clock을 더 많이

   먹을 수 밖에 없다는 단점이 있다. 게다가 unix 플래폼에서도 select 구현
 
   방식에 따라 sleep time이 변화가 있다. (3. 결론 참고)
  

   nanosleep은 sleep이나 usleep에 비해 signal에 영향을 받지 않는다는 장점이 있다.

 
   대부분의 UNIX OS(특히 Linux) kernel timer는 1/HZ정도로 맞추어져있으며,
  
   한 thread내에서 sleep등으로 context switching이 일어날 경우 다른 thread를

   수행하고 다시 현재의 thread로 돌아오는 시간은 최소 > 10ms가

   되며, 이것은 Intel Platform에서 지원하는 timer 주기와 맞물린다고 한다.

   (이에 대해선 linux의 jiffies설정과 기타 문서 참조.)

   따라서 실제로 thread내에서 usleep이든, nanosleep이든 sleep할 수 있는 최소의

   시간은 >1/HZ(10ms intel)가 되어야하며, 이것은 1/100초 즉, 10msec라고 할 수 있다.

   실제 sleep할 수 있는 시간은 10msec가 아닌 60msec정도가 한계인 경우(irix,solaris

   혹은 linux)도 있다.  이것은 또한 사용자 레벨에서 줄 수 있는 최소의 sleep time이라

   볼 수 있다.

   하지만 nanosleep에서는 SCHED_RR이나 SCHED_FIFO (sched_setscheduler) 설정에 따라
  
   busy-wait상태가 되면서 2ms 까지도 보장해준다고 한다. 이것은 time critical한

   부분에서 쓰일 수 있다.


   좀더 자세한 사항은 man page를 참고.

   man sleep
   man usleep
   man nanosleep


   마지막으로 assembly clock 소모성 sleep 에 대한 이야기인데 (busy-wait이다),

   이것은 주로 nop과 같은 1~3 cpu clock을 여러번 inline asm을 통해 호출함으로써

   얻을 수 있는 시간차를 사용하는 것이다. scheduling 방식에 따라 cpu intensive한

   sleep일 수도 있다. 하지만 CPU와 architecture 등 하드웨어에 따라 clock수가
 
   다르고 수행 시간이 틀려 통일성을 얻기 위해서는 다소 어려운 점이 있다.

   특히 포팅문제가. -.-;


3. 결론

   실제 sleep time은 예상한 시간보다 더 많이 sleep한다. (특히나 <1s 용 sleep인 경우)
 
   gettimeofday를 이용한 time estimate 측정툴에 대한 결과는 다음과 같다.

   sleep은 대상에서 제외된다.(1s 단위는 매우 잘 지켜진다. --;)


   실제로 우리가 원하는 <1sec 시간을 설정하였음에도 불구하고, 시간은 제대로

   지켜지지 않고, 약 +10%정도 추가 지연시간을 갖게 된다. 이렇게 되면 매우 힘들게 된다. -.-;
 
   FreeBSD와 Linux에서 동시에 테스트되었다. (소스 부록은 4. 부록편을 참조.)

      my_nanosleep(0,100000000L); //estimate time usleep : 0.109942
      // 0.1sec보다 10%더 많이 쉬었다. -.-;

      usleep(100000); // estimate time usleep : 0.109575
      // 마찮가지다. 0.1sec보다 10%더 많이 쉬었다. -.-;

   my_selectsleep(0,100000);
      // FreeBSD: estimate time usleep : 0.109907
      // Linux: estimate time usleep : 0.099969
      // FreeBSD는 select도 다른것들과 마찮가지다.


   이에 대한 테스트는 계속 진행중이며,

   당연하겠지만 가끔씩 시간이 원하는 sleep time의 2배까지 튀는 현상도 발생한다.
   (Linux에 경우이다., FreeBSD에서도 10%이상 튀는 경우가 역시 발생한다.)

   역시 일반적인 설정으로는 time critical한 부분에서는 사용할 수가 없겠다는

   결론에 이른다. 좀더 테스트가 필요하다.


   한편, asm sleep은, nop 으로 1000개를 inline asm으로 발생시키는 경우

   Pentium MMX 200 : nop 명령 38600000 번이 0.1s sleep
   P3-500 1Mcache 4way : nop 명령 96500000 번이 0.1s sleep

   busy-wait이므로 오래 wait을 하면 전체 process의 응답 속도에 엄청난 영향을

   미친다.


4. 부록

[sleep_functions.c]

// sleep functions
//
// Lee, Hongki <orinmir _at_ chonga _dot_ pe _dot_ kr> : http://chonga.pe.kr

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>

int my_setsched(iPolicy);
    struct sched_param p;
    //int iPolicy=SCHED_RR;

    p.sched_priority = sched_get_priority_max(iPolicy);
    return sched_setscheduler(0,iPolicy,&p);
    // error when -1 return
    // then check the errno.
}

// nanosleep wrapper function
void my_nanosleep(time_t sec,long nsec)
{
    struct timespec req;

    struct timespec rem;

    if ((sec==0) && (nsec==0)) {
        req.tv_sec=0;
        req.tv_nsec=999999999L; // 999 999 999
    }
    else {
        req.tv_sec=sec;
        req.tv_nsec=nsec; // 999 999 999
    }

    //rem.tv_sec=0;
    //rem.tv_nsec=0;

    //while (nanosleep(&req, &rem))
    while (nanosleep(&req, &req))
    {
        if (errno != EINTR)
            break;
    }
    return;
}


void my_selectsleep(int sec,int msec) {
    struct timeval tv;
    tv.tv_sec=sec;
    tv.tv_usec=msec;               
    select(0,NULL,NULL,NULL,&tv);
    return;
}

 

// 소모 cpu clock 측정
// system이 boot up된 이후에 수행된 clock을 담고 있다고 한다.
// 시작과 끝부분을 검사하면 되는 걸로 알고 있음.
__inline__ unsigned long long int rdtsc()
{
       unsigned long long int x;
    __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
     return x;
}

// 테스트를 위한 inline asm busy wait sleep
__inline__ void asm_sleep(unsigned int sleepclocks) {

    int i=0;
    for (i=0;i<sleepclocks;i++) {
        //__asm__ volatile ("nop ; nop ; nop ; nop");
        __asm__ volatile ("nop ; "); // 486 takes 1clock, 386 taks 3clocks
    }
    return;
}

__inline__ void asm_sleep_1000nop() {

    // 486 takes 1clock, 386 taks 3clocks
    // 586 ?
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");
    __asm__ volatile ("nop ; nop; nop; nop; nop; nop; nop; nop; nop; nop;");

 return;

}


 


덧글

  • 오서비네 2007/08/12 16:54 # 답글

    * Application 중 FIXSALE 프로세스의 CPU 과다 점유 현상
    - 문제점 : Open 직전에 발견한 문제점으로 일개 Application 에 불과한 FIXSALE 프로세스가
    CPU 를 30 ~ 40 % 사용함. DEC 에서 제공하는 usleep 함수에 버그가 있음.
    10 ms 이하의 시간을 제대로 관리못함.
    - 수정사항 : while 문 안의 usleep argument 을 100*1000 으로 수정
    메시지를 받으면 usleep 타지 않고 곧바로 while 을 타기 때문에 값을 증가해도 문제없음.
    - 수정 소스

    //#define DEF_WAIT_TIME 100
    #define DEF_WAIT_TIME 100*1000
    usleep(DEF_WAIT_TIME);


    - 참고로 추후에는 select 를 이용하여 다음과 같이 수정할 예정임

    SleeNew(100);
    int SleepNew(long msec)
    {
    struct timeval timeout;

    timeout.tv_sec = msec / 1000L;
    timeout.tv_usec = (msec % 1000L) * 1000L;

    return select( 0, 0, 0, 0,(struct timeval *)&timeout);
    }

  • enatubi 2017/07/26 16:09 # 삭제 답글

댓글 입력 영역