箱ひげ図
Table of Contents
Pixel 8a update
ふとアップデートを確認したら、システムに重大な問題があるから更新しろと 出てた。そんなの夜中にでも実施するのが筋だろう。素人はそんなの気にしない だろうに。メーカーの怠慢だと思うぞ。
で、実施したらネットワークエラーですって。時間を置いて試してみてください。 翌日もそのまた翌日も試したけど、同様なエラーですよ。アプリのアップデートは 何の問題もなくWiFi経由で出来るんだけどな。不思議な事だ。
ネットワークを替えてみろとも案内してたぞ。家の中のWiFiでは不満が有るの? 天気も良い事だし、スマホを持って公園へ繰り出そう。WiFiの圏外が狙いね。 家の中ではモバイルネットワークの4Gは元気が無かったけど、外だと強力に 入感してた。電波の特性なんですかね? もし、あまねく5Gを利用できる様に なっても家中では、その恩恵に預かれないのかな(まあ、そんな心配はこの過疎地 では不要です。絶対にやってこないから)。
藤棚の下のベンチに腰を下して、ああ、藤のさやが沢山ブラブラしてんな、種を 採取して、炒ったら酒のつまみになるかしらん。とか思っているうちに、 すんなりとアップデートできた。どういうこっちゃ?
を見ると、公開から順次に受信できる。1週間半ぐらいかかると説明されてる。 リリース日は2/5となってた。今日は16日だからギリギリだったのかな。 それとも、たまには外の空気を吸ってくださいって事なのかな。
確定申告
毎年やってくる。今年はWindowsが無い状態なんだけど、申告できるのかな?
新らしいスマホが有るんで、e-Taxをやってみるか。その前に医療費控除の集計を しとく必要が有るな。使用医療費の内訳が、この時期に役場から届くんだけど、 ギリギリに届いた。ちょっとヤキモキしたぞ。11,12月は集計の時期の問題で 掲載されていない。まったく役所間の連携が取れていないな。抜けてる部分は 領収書を用意して補完しなきゃならない(だから医療費控除の集計)。 庶民の迷惑返りみずですよ。
Lubuntuにも、LibreOffice calcが付属してるんで、こいつの出番だな。
iryouhi_form_v3.xlsx
を起動して、1データだけ入力。それを別なファイル名で
保存しようとしたら、どこかのセルにパスワードが設定されてるので、保存
できませんと言ってきた。こんな事が有るだろうという予感が的中しましたねぇ。
だから、被害が甚大になる前に確認したのさ。
ゴチャゴチャやってたら、EXCELフォーマットを捨ててodsフォーマットに変換したら
無事にセーブできた。去年はWindows上で動作するLibreOfficeを使ったんだけど、こ
んな苦労は無かったような。。種になる iryouhi_form_v3.xlsx
は去年と同等っぽい
から、LibreOfficeの互換性問題の噴出って事ですかねぇ。まったく、どこに落し穴が
潜んでいるか分かったものじゃない。
女房のスマホで始めてみたはいいんだけど、ごちゃごちゃ入力させられるんで挫折した。 大体あんな小さな板っきれ上に仮想キーボードなんて狂気のさただと思うぞ。 調べてみたら青歯接続の外部キーボードが有るみたいだね。でも、年に一度しか使わ ないのに、そんな物用意したくないぞ。スマホなんて糞くらえの昭和一徹者であります。
キーボードは大事だよ。カウボーイは馬がへたって倒れても鞍だけは持っていくって HHKなキーボードを作った和田先生がおっしゃっていた。最近のノーパソに鎮座してる キーボードは貧弱で嫌い。昔のThinkPadについてたキーボードが好きだったな。 キーに厚みがあり、指を包む感覚が好きだよ。これ昔のIBMゴルフボール式のヘッドが ついていた電動タイプライターに採用されてたのかな。一打鍵ですっかり虜になった ものだ。そのキーボードがノーパソにも採用されたんで、キーボード欲しさに ThinkPadをづっと使い続けていたのさ。今は貧弱キーボードしかないのを我慢すると すれば、BTOで英語キーボードを選べるのが唯一の利点かな。
確定申告はそんな訳でLubuntu上のChromeでやった。無事に終了。証拠書類の添付とかの 事務処理は女房に任せてしまえ。オイラーの仕事はコンビニで印刷してくる事だな。
hdd speed (2)
前回hddのスピードチェックをやった時、/usr/localエリアは、他と比べて バラツキが多かった。何故? 調べてみたい。
その前に、前回は箱ヒゲ図だったけど、今回は、生データから統計言語Rを使って 四分位数を求めてみたので再掲。
sakae@lu:set$ paste root local var >all sakae@lu:set$ R > x <- read.table('all') > summary(x) root local var Min. :79293405 Min. :73698060 Min. :67983402 1st Qu.:80865035 1st Qu.:75334409 1st Qu.:68496325 Median :81519035 Median :76204658 Median :69171881 Mean :81402990 Mean :76352235 Mean :69143347 3rd Qu.:82090118 3rd Qu.:77614988 3rd Qu.:69634300 Max. :82747474 Max. :78899623 Max. :70374228
生データにはヘッダーが付いていないので、それをRで読むとV1,V2 みたいな仮の名前が付けられる。ちょいと結果を編集したよ。
Q: localエリアへの書き込みは、バラツキが他と比べて 大きいように思える。これについても、何か推測できますか?
A: ### ハードディスクの書き込み速度と位置依存性の検証
このデータから、以下の傾向が見て取れる。
- 書き込み速度はディスクの外周ほど速く、内周ほど遅い
- `root`(外周)では、中央値が約81.5MB/s、`/var`(内周)では約69.2MB/sであり、約15%の速度低下が確認できる。
- これは、HDDの構造上、外周ほど1回転で読み書きできるデータ量が多いため、リニア速度が向上するためである。
- `/usr/local`(やや内周)の書き込み速度のバラツキが大きい
- `root` と `/var` の四分位範囲(Q3 - Q1)は、それぞれ 1.2MB/s, 1.1MB/s であるのに対し、`/usr/local` は 2.3MB/s と2倍近く大きい。
- これは、内周に近づくとセクタ密度が高くなり、ディスクキャッシュの影響を受けやすくなるためと考えられる。
### 3. 考察
#### 3.1. 書き込み位置と速度の関係 今回のデータは、HDDの書き込み速度がディスクの物理的な位置に依存することを裏付ける。一般に、HDDは外周部分では1回転あたりの線速度が高く、より多くのデータを処理できる。逆に、内周に行くほどトラックあたりのデータ量が少なくなり、書き込み速度が低下する。
具体的な要因としては以下が考えられる。
- 角速度(回転数)は一定 であるが、外周では線速度(データ処理量)が速い。
- セクタ密度が内周では高く、ヘッドの移動やキャッシュの影響を受けやすい。
- CAV(Constant Angular Velocity:一定角速度)方式のHDDでは外周の転送速度が有利。
#### 3.2. `/usr/local` におけるバラツキの原因 `/usr/local`(やや内周)の書き込み速度のバラツキが他よりも大きい理由について、以下の可能性が考えられる。
- ディスクキャッシュの影響
- `/usr/local` は外周と内周の中間に位置するため、HDDのキャッシュやOSのバッファ管理の影響を受けやすい可能性がある。
- 書き込み時にキャッシュがヒットするかどうかで速度が変動する。
- ヘッドのシーク動作
- `root`(外周)は比較的一定の位置で書き込みが行われるが、`/usr/local` は他のデータと混在しやすく、シーク時間の影響を受けることがある。
- `/var`(内周)は、ログ書き込みなどで頻繁にアクセスされるため、HDDの内部スケジューラが最適化し、結果として変動が抑えられる可能性がある。
- パーティションの断片化
- `/usr/local` はソフトウェアのインストール領域として使われることが多く、ファイルが細かく分散している可能性がある。
- 断片化が進んでいると、連続書き込みできず、速度のバラツキが発生する。
そういう見方ですか。何か考えてみよう。
dd
その前に、ddコマンドが、どう実装されてるか見ておくか。
ob$ dd if=/dev/zero of=dmy bs=1M count=100 100+0 records in 100+0 records out 104857600 bytes transferred in 1.576 secs (66534010 bytes/sec)
こんなんだ。書き込みに要した時間が報告されてる。これって内部的にtimeを 使ってる?
misc.c
/* SIGINFO handler */ void sig_summary(int notused) { : clock_gettime(CLOCK_MONOTONIC, &now); timespecsub(&now, &st.start, &elapsed); : if (!(ddflags & C_NOXFER)) { dprintf(STDERR_FILENO, "%lld bytes transferred in %lld.%03ld secs " "(%llu bytes/sec)\n", (long long)st.bytes, (long long)elapsed.tv_sec, elapsed.tv_nsec / 1000000, bps); }
st.startはddの起動直後に取得してる。そして、SIGINFOのハンドラーって事は、任意の時点での情報を表示出来るんだな。そして、秒以下は 控え目に、msに抑えてる。これが現実的かな。リナだと、
sakae@lu:tmp$ dd if=/dev/zero of=dmy bs=1M count=1000 1000+0 records in 1000+0 records out 1048576000 bytes (1.0 GB, 1000 MiB) copied, 0.445821 s, 2.4 GB/s
us単位まで表示してくれて、よりルーレットっぽい使い方に適しているな。最近は円盤が 回転するタイプは影を潜めてSSDが主流だからなあ。
箱ひげ図
書き込むファイルサイズを変更した時、スピードはどう変化するか? 出力を直接gnuplotに渡せるようにした。awk -v を使って、awkの 中へ、外部の値を取り込むのが味噌かな。
#! /bin/sh dmy=/usr/local/dmyfile meas() { for t in `seq 20`; do dd if=/dev/zero of=$dmy bs=1M count=$sz 2>&1 | awk -v xl=$sz '/trans/{print xl, $1 / $5 / 10^6}' rm -f $dmy done } for sz in 1 3 10 30 100 300 1000; do meas done
サイズは適当ってか、最初 1,5,10,50,100,500の様に硬貨の値にしたんだけど、それじゃ あんまりだ。1000円硬貨なんて無いぞ。ってな事で、対数的な増加を目論んだ(log(3)=0.477)。 まあ、遊び 心だわな。
なお、関数とかについての正しい記述方法をusbfadmで参照しておく。肝は、関数内での引数処理。引数は 位置パラメータとして、$1 $2 … の様に参照する。関数内で使用する変数が、外に 漏れないようにlocal宣言するのが良い。
/etc/rc とかを見ると、ローカル変数は、冒頭文字を '_' で始めるように統一 してた。こう決めてしまえば、一見で判別できるな。オイラーが間に合わせで書いた のは、昔のBASIC時代みたいに、全ての変数をグローバルとしてた。これが許されるのは 、せいぜい10行以下のコードでしょう。でも、往々にして肥大化してくからなあ。
# read user's input with readline functionality # outputs echoed to stdout # # usage: rl_wread prompt-str default-str [completion words ....] # function rl_wread { local prompt="$1"; shift local default="$1"; shift local retval : }
これを箱ひげ図にすると、こうなる。
沢山のサイズと言う割には、1Mの時の箱ひげが圏外になってる。
> summary(x$V2) Min. 1st Qu. Median Mean 3rd Qu. Max. 349.5 349.5 349.5 349.5 349.5 349.5
こんな風に飛び抜けた値になってた。それはそうと、この箱ひげ図では、結構な割合で 外れ値が有るな。外れ値に認定されるには、(Q3 - Q1) * 1.5 を越えたものらしい。 そして、その境界をひげの両端として、あたかも最大、最小の値であるがごとく示す のが約束のようだ。 25%から75%の範囲にあるデータが並の値。その差の1.5倍を越えると、外れ(過少、もし くは過大)だよとな。
昔の日本人の収入は、まあ皆横並びだった。最近は格差が目立ってきて、極端に貧乏か 大富豪になっちまった。外れ値が増えたって事だ。それを自己責任と称して恥じない 言説がまかり通ってる。
昔、統計局が統計処理を間違って都合の良い統計を発表してた。箱ひげ図が提示されたら きちんと外れ値を表示してるか確認しよう。統計的に外れ値が含まれてましたから、 それを除外して発表しましたとシレっと言うかも知れないぞ。
gnuplotでも、確認できる。
gnuplot> stat 'sel3.log' using 2 : Minimum: 32.0993 [ 6] Maximum: 80.6597 [ 7] Quartile: 65.5360 Median: 68.3854 Quartile: 69.9396
このデータから、外れ値になる上限と下限を求めてみる。
sakae@lu:tmp$ echo '69.9396 + (69.9396 - 65.5360) * 1.5' | bc 76.5450 sakae@lu:tmp$ echo '65.5360 - (69.9396 - 65.5360) * 1.5' | bc 58.9306
MaxとMinの値は、明かにこれらのリミット値から逸脱してるので、外れ値と認定 されるな。
Q: このような値を得た時、フェルミ推定で、標準偏差を求められるか?
A: 標準偏差は通常、データの個々の値が必要ですが、要約統計量(最小値、最大値、四分位数、中央値)からの**推定**も可能です。 以下の方法があります。
### ① 四分位範囲 (IQR) からの推定 標準偏差 (\(\sigma\)) は四分位範囲 (\(IQR = Q3 - Q1\)) から近似できます:
\[ \sigma \approx \frac{IQR}{1.35} \]
### ② 範囲 (Range) からの推定 標準偏差はデータの範囲 (Range = 最大値 - 最小値) からも推定できます。 \[ \sigma \approx \frac{\text{Range}}{4} \]
考察
って言う程のものでは無いけど。1Mの時はスピードが速いな。これって、反比例の恩恵を 受けていないか? スピードは、bytes/sec で、正規化してる。転送時間が小さければ、見掛け上スピードが 速く算出されてしまう事になるな。 それに、HDD自身が内蔵してる8Mのキャッシュが有効に働いている可能性が有るな。
その伝で言えば3Mの時もキャッシュの恩恵を受けそうだけど、そうはなっていない。 むしろ10M以上のサイズの時より遅くなってる。何せ相手は円盤が回るルーレットです から。。考えるだけ無駄。競馬で予想した馬が来ないのは何故って不毛な思考 みたいなものだな。
外れ値に注目すると、下振れになってる。これは、通常よりも転送に要する時間が 延びていると解釈できるな。速い方のリミットは(多分)ハードだけで決まってしまう けど、遅くなる理由なら、幾らでも考えられるぞ。
それから、1Gを書き込んだ時のバラツキは、他と比べて小さい。多分、 パーティションの断片化 が有る領域を全て使う事になってしまう書き込みサイズなんで、その影響を飲み込んでしまい、 表面化しないのだろう。
もう、これぐらいにしておこう。
clock_gettime
時間測定の要になってるシステムコールを実験。
#include <stdio.h> #include <sys/time.h> int main(){ struct timespec timeout, start, stop, elapsed; timeout.tv_sec = 1; timeout.tv_nsec = 500000000; clock_gettime(CLOCK_MONOTONIC, &start); nanosleep(&timeout, NULL); clock_gettime(CLOCK_MONOTONIC, &stop); timespecsub(&stop, &start, &elapsed); printf("nanosleep: expected %lld.%09ld actual %lld.%09ld\n", (long long)timeout.tv_sec, timeout.tv_nsec, (long long)elapsed.tv_sec, elapsed.tv_nsec); }
何回か繰り返してみた。
vm$ ./a.out nanosleep: expected 1.500000000 actual 1.508625878 nanosleep: expected 1.500000000 actual 1.508305555 nanosleep: expected 1.500000000 actual 1.510205207 nanosleep: expected 1.500000000 actual 1.507978285
1.5秒の待ちを指定しても10msぐらいの不確かさが有るんだな。ナノスリープってのは その桁まで指定できるよって事だけで、現実は全く異なるとな。
nanosleep: expected 1.500000000 actual 0.000001122 nanosleep: expected 1.500000000 actual 0.000000296 nanosleep: expected 1.500000000 actual 0.000000997 nanosleep: expected 1.500000000 actual 0.000000327 nanosleep: expected 1.500000000 actual 0.000000851
待ちを無しにした、いわゆるシステムコールの実行時間。このデータを多数収集 して、箱ひげ図にしてみるのも一興かと。フェルミ推定で標準偏差を求めるとか 乱数検定してみるとかも興味のある所だ。
ちょっとカーネル側も参照してみる。
(gdb) bt #0 binuptime (bt=<optimized out>) at /usr/src/sys/kern/kern_tc.c:188 #1 nanouptime (tsp=0xffff80001c966c00) at /usr/src/sys/kern/kern_tc.c:217 #2 0xffffffff81d66220 in timeout_hardclock_update () at /usr/src/sys/kern/kern_timeout.c:598 #3 0xffffffff818693d8 in clockintr_hardclock (cr=<optimized out>, frame=0xffff80001c966d20, arg=<optimized out>) at /usr/src/sys/kern/kern_clockintr.c:442 #4 0xffffffff818699ff in clockintr_dispatch (frame=0xffff80001c966d20) at /usr/src/sys/kern/kern_clockintr.c:212 #5 0xffffffff81f53745 in lapic_clockintr (arg=<optimized out>, frame=...) at /usr/src/sys/arch/amd64/amd64/lapic.c:481 #6 0xffffffff816ec8fa in Xresume_lapic_ltimer () #7 0x0000000000000000 in ?? ()
この辺はタイマーやらが頻繁にアクセスしてくるので、余り長居は禁物です。 目指すはCPUが持ってる、高分解能なカウンターです(よね)。
type
timeコマンドの事を書いたら、typeってコマンドを教えていただいた。コマンドの 種類を報告してくれるものだそうだ。ちょいと実験。
vm$ type type type is a shell builtin vm$ type pwd pwd is a shell builtin vm$ type cd cd is a shell builtin
良く使うコマンドはkshに内蔵されてるのか。以下、思い付くままに結果だけを 羅列してみる。
time is a reserved word for is a reserved word if is a reserved word ls is an alias for 'ls -F' awk is /usr/bin/awk emacs is a tracked alias for /usr/local/bin/emacs
ちょいとemacsのタイプが気になる。
vm$ ls -l /usr/local/bin/emacs* lrwxr-xr-x 1 root wheel 10 Jan 5 08:38 /usr/local/bin/emacs@ -> emacs-29.4 -rwxr-xr-x 1 root bin 7777136 Sep 28 07:42 /usr/local/bin/emacs-29.4* -rwxr-xr-x 1 root bin 32624 Sep 28 07:42 /usr/local/bin/emacsclient*
成程、リンク・ファイルは、こんな表示をするのか。じゃ、その実装は?
vm$ cd /usr/src/bin/ksh vm$ fgrep 'reserved word' *.c c_ksh.c: shprintf(" is a reserved word");
直ぐ見る可がOpenBSDの良い所。そして、直ぐgdbも可。
vm$ doas vi Makefile CFLAGS= -g -O0 ;; add this line vm$ doas make
Ready to gdb
vm$ gdb ksh (gdb) b shprintf Breakpoint 1 at 0x4a1d0: file io.c, line 155. (gdb) r Starting program: /usr/src/bin/ksh/ksh vm$ type emacs Breakpoint 1, shprintf ( fmt=0x20000000001 <error: Cannot access memory at address 0x20000000001>) at io.c:155 (gdb) bt #0 shprintf ( fmt=0x20000000001 <error: Cannot access memory at address 0x20000000001>) at io.c:155 #1 0x000003238efa7751 in c_whence (wp=0x325a95dd0e8) at c_ksh.c:477 #2 0x000003238efa7ab3 in c_type (wp=0x325a95dd0d8) at c_ksh.c:553 #3 0x000003238efbfa59 in call_builtin (tp=0x325a95bbc10, wp=0x325a95dd0d8) at exec.c:1034 #4 0x000003238efbeb21 in comexec (t=0x325a95d9b50, tp=0x325a95bbc10, ap=0x325a95dd0d8, flags=0, xerrok=0x72dd9903eea0) at exec.c:543 #5 0x000003238efbcdec in execute (t=0x325a95d9b50, flags=0, xerrok=0x72dd9903eea0) at exec.c:132 #6 0x000003238efd22bf in shell (s=0x325a95e7090, toplevel=1) at main.c:650 #7 0x000003238efd1998 in main (argc=1, argv=0x72dd9903f248) at main.c:452
shprintfをそのままBPしちゃったけど、ちと深すぎるみたいなので、 c_whence
ぐらい
にBPを置くのが良さそう。ここまで、ものの1分ぐらいですか。何の労もなく、核心
に到達した。後はじっくり鑑賞するだけーーー。
閲覧が終了したら、make clean しとくか、rm *.o *.d ぐらいをしておけば良いだろう。 本当は、/tmpあたりにcpして、ツリーを汚さないのがいいんだけど、ものによって、 本体のツリーの中でしかコンパイルできない事がある(ヘッダーファイル見付からんエラー)。
これ、 c_whence
関数の最後の部分。
default: shprintf("%s is *GOK*", id); break;
どれにも当てはまらない場合、この表示が出る(はず)なんだけど、GOK って何よ?
=God only knows. 神のみぞ知るところです。/そんなことは誰にも分かりません。/診断不能。
出川の口癖、オーマイガーは良く聞くけどな。今度彼に会ったら教えてあげようか。 あちらの人は良く使うのだろうか?
本腰を入れて調べるなら、etags *.[ch] して、あちこちにジャンプ出来るように地図 を作成しておくと吉。replに到達するまでの動きを調べるのがセオリーだな。
etc
世界同時発表の修正勧告。
OpenBSD 7.6 errata 008, February 18, 2025: sshd(8) denial of service relating to SSH2_MSG_PING handling. ssh(1) server impersonation when VerifyHostKeyDNS enabled.
詳細は、 MitM attack against OpenSSH's VerifyHostKeyDNS-enabled client このBUGをトリガーにして、同様事例が無いか精査してる。人のふり見て我が身を 直せが祖母の口癖だったけど、このレポートを上げた方の祖母なりの言い付けを 守っているのかな。
まて、この言い付けって日本独自のものかも。いわゆる空気読めを強いる文化の 醸成に寄与してるのかな。個性豊かにとは、いかないからな。
以下アラカルトって事で、まずは、久しぶりのrubyネタから。
最速Rubyリファレンスマニュアル検索 るりまサーチってイケてるね
RubyでThreadがデッドロックしたときにバックトレースを表示する。あるいはRubyに送ったパッチの話
プロと読み解くRuby 3.4 NEWS 笹田先生、遠藤さん、ご活躍。懐かしいです。
VMware Workstation Proで仮想マシンを快適に使うための基本設定
そのうちに、vmrunの説明がなされるのかな? 乞うご期待しましょ。
sakae@lu:~$ type vm-vm vm-vm は `vmrun -T player start /var/my/vmware/OpenBSD/OpenBSD.vmx' のエイリアスです
おまけ
ChatGPTにsvgファイルは解析できるかと質問したら、まかせて下さい、だった。 実際にUploadしたら駄目でしたんで(gnuplot作成のそれには、有効なデータが含ま れていないって判定)、生データ下さい。で、こんな事を言ってきた。
データを確認しました。書き込みサイズごとに20回のサンプリングが行われており、転送スピードのばらつきを分析できます。 これを基に、箱ひげ図を作成し、考察を進めます。
箱ひげ図を作成しました。以下の点が読み取れます:
- 1MBの書き込み速度(350MB/sec)は図に含まれていない
- 明らかに他のサイズよりも速く、HDDのキャッシュ(8MB)に収まるため、キャッシュ効果が大きいと考えられます。
- 3MB以上では速度が大幅に低下
- 3MBになると、速度は大きくばらつきながらも50~80MB/sec程度に低下。
- HDDキャッシュ(8MB)の影響が限定的になり、ディスクの実効速度が支配的になった可能性。
- 書き込みサイズが増えると速度のばらつきが減少傾向
- 1000MB(1GB)では、中央値がほぼ一定で、ばらつきも比較的小さい。
- これはHDDの連続書き込み性能が安定していることを示唆。
- 300MB地点に若干の異常点(低速値)が見られる
- 43MB/sec 付近の外れ値があり、一時的な要因(ディスクのシーク時間増大や他のI/O競合など)の影響の可能性。
### 考察:
- 1MB書き込みはHDDのキャッシュに収まるため非常に高速
- 3MB以上ではキャッシュを超え、HDDの本来の書き込み速度が反映される
- 書き込みサイズが増えるとばらつきが減少し、連続書き込み時の安定性が向上
- 外れ値はI/Oの競合やHDDの内部処理による影響の可能性
この結果を踏まえ、さらに詳細な分析(例えばHDDキャッシュ無効化のテストなど)を行うことで、HDDの挙動をより深く理解できるかもしれません。
まあ、妥当な分析だな。