トップ «前の日記(2003年12月09日) 最新 次の日記(2003年12月11日)» 編集
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|10|12|
2009|02|03|06|07|10|11|12|
2010|01|02|03|04|07|09|10|11|12|
2011|01|03|04|05|06|07|08|10|
2012|01|06|08|09|10|12|
2013|01|02|03|04|07|09|11|12|
2014|01|03|04|05|06|09|
2015|04|
2016|01|08|
ここは旧えびめもです。えびめも2に移行します(2016/12/1)

2003年12月10日 快晴

usleepの真実

usleep()は指定した時間(マイクロ秒単位)で実行を遅延してくれる便利な関数でusleep(1)などとしてCPUのロードアベレージを抑えることに利用したりするが、皆さんご存知のとおりnマイクロ秒『以上』遅延するという仕様になっているので1マイクロ秒遅延を指定したところで1秒待たされても文句は言えない。では実際のところどうなっているか調べてみた。
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
 
unsigned long test_array[]={1,10,100,1000,2000,5000,10000,19000,19999,20000,20001,21000,50000,100000,200000,500000,0};
 
int sleep_test(unsigned long sleep, int count){
  int i=0,d,offset;
  struct timeval start,end;
  struct timezone dontuse;
 
  // gettimeofday()関数の実行時間を調べる
  gettimeofday(&start,&dontuse);
  gettimeofday(&end,&dontuse);
  offset=
    ((end.tv_sec)*1000*1000+(end.tv_usec))-
    ((start.tv_sec)*1000*1000+(start.tv_usec));
 
  gettimeofday(&start,&dontuse);
  // =================== 計測開始
  for(; i<count; i++){
    usleep(sleep);
  }
  // =================== 計測終了
  gettimeofday(&end,&dontuse);
 
  d=((end.tv_sec)*1000*1000+(end.tv_usec))-
    ((start.tv_sec)*1000*1000+(start.tv_usec))-
    offset;
  printf("%d,%d\n",sleep,d/count);
  return d;
}
 
int main(){
  unsigned long sleep;
  int count;
  int i;
  printf("usleep(マイクロ秒),実時間マイクロ秒\n");
  for(i=0; test_array[i]!=0; i++){
    sleep=test_array[i];
    count = 20*1000*1000/sleep;
    if(count>1000)
      count=1000;
    sleep_test(sleep, count);
  }
}
結果(i386, kernel-2.4.23,システム負荷が十分低い条件)
usleep(マイクロ秒),実時間マイクロ秒
1,19992
10,19999
100,19999
1000,19999
2000,19999
5000,19999
10000,19999
19000,29999
19999,29999
20000,29999
20001,39999
21000,39999
50000,59999
100000,109999
200000,209999
500000,509999
結果(sh3, kernel-2.4.21,システム負荷が十分低い条件)
usleep(マイクロ秒),実時間マイクロ秒
1,19997
10,19999
100,19999
1000,19999
2000,19999
5000,19999
10000,19999
19000,29999
19999,29999
20000,29999
20001,39999
21000,39999
50000,59999
100000,109998
200000,209996
500000,509992
i386もsh3も同じ傾向になった。

結果、usleep(1)としても20msecウェイトすることが分かった。usleep(20000)として20msecウェイトをかけると30msecウェイトする。とにかく約10msec単位に切り上げられることが分かった。HZが100だし。システム負荷(ロードアベレージ)が高い時のデータはどかたか調べてください。特にI/Oオリエント(割り込みが沢山入っている状態)の時はuserland/kernelの切り替えが多く発生し、コンテキストスイッチが起こりやすい状態?かもしれません。

サルサ

水曜日はレディアン春日井でemiko先生の日だけど、くしゃみ鼻水はなづまりがひどかったので休んだ。こんな日に参加しても相手に迷惑かけるだろうから。

ストーブ

石油ファンヒータを引退させ、石油ストーブを復活させた。この前徹夜組を含め、24時間連続でファンヒータを運転させたら丸一日でタンクが空になってあわてたからだ。

ストーブに変えて静かになった。しかもワイヤレスで部屋中移動できる。やっぱ現代はワイヤレスの時代だ。お湯も沸かせるし。お湯が沸くなら100度以上はあるに違いないが、ストーブの表面は何度くらいあるのか?気になる。放射温度計で測定した。放射温度計とは、万物は温度に応じたエネルギーの赤外線を放射しているので、その量を測定すれば温度がわかるという原理のもので、触れないほど熱い物とか高電圧で危険な物、触ると不衛生になってしまう食品などを触らずに測定できる便利なものだ。なぜ工房にあるかというとこういうとき(どういうとき?)に役立たせるために置いてある。

およそ300度だった。(3へ〜)

ちなみに岩崎は36度で、新谷は35.5度だった。