RAIDをやめた

2017/05/30

同じく記録だけこのしておく。

メインのPCは今までAdaptec RAID 2405でRAID 1Eにしていたのだが、やめてしまった。

RAIDにしていても、
  1. 個人用PCだと、メディア(HDDとかSSD)は数が少ない。相対的にそれ以外のパーツが多くて、障害発生原因はメディアばかりではないということになる。業務システムでの数の暴力とは条件が違いすぎる。
  2. 同一筐体にある同一RAIDグループに属するメディアは、なんとなく同時に壊れる気がする。同じ環境で同じような読み書きをしているのだから。だから、1つでも壊れると、全部交換したくなる。
  3. というか、メディア障害よりも、ソフトウェア的な問題のほうが多い。間違って消したとか。
  4. 実は個人用PCだと、しばらく使えなかったところで、死ぬわけではない。
  5. メディア障害が発生したら、壊れた奴だけ代えて業務続行という使い方をしない。そういう時はOSごと再インストールしている。
ということで、あまりRAIDのありがたみを感じなかった。

それよりもは、6に書いた通り、OSやソフトウェアはインストール媒体から再インストールして、ユーザデータはバックアップから戻すという使い方が多い。

結果、RAIDよりバックアップが重要だ、という方向に宗旨替えすることにした。


電源ボックスを交換した

2017/05/28

記録だけ残しておく。

メインマシンの電源ボックスを変えた。

今のところ何の問題もなく動き続けてくれてはいるのだが、買ってからおよそ7年半経過して、さすがになんとなく怪しい感じがするから、悪いけど引退してもらった。

買ったのはこれ。



SSR-750RMS

1万7千円ぐらいした。

特に絵はない。それに、今のところ、何事もなく動いているため、特に述べるべき感想もない。

そういえば、前の奴もSeasonicだった。外した時の写真を撮っておいたから、面白みもないがさらしておく。



外観はまぁ、ほこりが見えてますね、という程度か。 外から見ると、中に入っているファンがなんだかよくわからなくて、怪しい雰囲気を感じる。



San Ace 120と60でした。さすがに羽根の表面は汚れているが、肝心の中身のほうには、あまりちりやほこりが詰まっている感じがしない。



アップにしてみても、あまり汚れが目立たない。

本当はここで、中にぎっちりとほこりが詰まっていて、その中にゴキブリの卵や死体が点々と埋もれているような、あるいは、ふたを開けた途端にパンドラの箱を開けたがごとくこの世のありとあらゆる悪いものが噴出してくるような、そういう絵面を期待していたのだが、全然そんなことはなかった。

正直言って、面白くない。

7年半蓄えたお前のエネルギーはこの程度だったのかと。

F#での引数なしの関数の扱いについて

2017/05/16

なんとなく、F#での引数なしの関数の書き方がよくわからなくなってきたから、整理してみた。

1.単なる関数の場合

以下のプログラムを考える。

module  FTest
open System


// printfの戻り値であるUnit値を持つ定数になる
let func1 =     // unit
    printf "func1\n"


// unit値を引数にとる関数値になる
let func2 () =  // unit -> unit
    printf "func2\n"


[<EntryPoint>]
let main args =
    printf "main start\n"

    func1       // 意味なし
    func1       // 意味なし
    func2 ()    // ここで実行される
    func2 ()    // ここで実行される

    printf "main end\n"
    0


実行結果は以下となる。



上記では、func1自体は関数ではなくunit値の定数になっている。関数本体の実行はmainが呼ばれる前に行われてしまっている。

func2はunit値を引数に取る関数値である。C言語に例えるのなら関数ポインタの値であり、俺が思うところの引数なしの関数として振る舞ってくれる。

だから、func2については「func2 ()」を記述したところで、その関数の中身である「printf "func2\n"」が実行される。一方、func1はmain関数の中では実行されていない。

2.クラスのメソッドの場合
混乱するのが以下の場合だ。

module  FTest
open System


type CTest() =
    member this.func1 =
        printf "CTest.func1\n"


    member this.func2 () =
        printf "CTest.func2\n"


[<EntryPoint>]
let main args =
    printf "main start\n"
    let c = new CTest()

    c.func1       // ここで実行される
    c.func1       // ここで実行される
    c.func2 ()    // ここで実行される
    c.func2 ()    // ここで実行される

    printf "main end\n"
    0


これを実行すると下記となる。



func1の動きがさっきと違う。さっきと似た様なもんだろうと思うのだが、今度はmain関数の中で実行されている。何なのか?

まぁ、よくわからんが、たぶん自己識別子であるthisが暗黙の引数として扱われている、ということなのではないだろうか。だから「c.func1」が記述されたところで、初めて実行されると。

ということで、次にこうしてみた。

3.スタティックなメソッドの場合

module  FTest
open System


type CTest() =
    static member func1 =
        printf "CTest.func1\n"

    static member func2 () =
        printf "CTest.func2\n"


[<EntryPoint>]
let main args =
    printf "main start\n"
    let c = new CTest()

    CTest.func1       // ここで実行される
    CTest.func1       // ここで実行される
    CTest.func2 ()    // ここで実行される
    CTest.func2 ()    // ここで実行される

    printf "main end\n"
    0


実行するとこうなった。



予想外な結果である。俺としては、CTest.func1は、タイミングは別としても1回だけしか実行されないのではないかと考えたのだが、そうでもないらしい。

4.let束縛にする

なんかむかついたから、こうしてみた。

module  FTest
open System


type CTest() =
    let func1 = printf "CTest.func1\n"


    static member func2 () =
        printf "CTest.func2\n"


    member this.func3 = func1

[<EntryPoint>]
let main args =
    printf "main start\n"
    let c = new CTest()
    printf "new CTest() owari\n"

    CTest.func2 ()  // ここで実行される
    CTest.func2 ()  // ここで実行される
    c.func3         // 意味なし
    c.func3         // 意味なし

    printf "main end\n"
    0


実行結果はこうなる。



で、ここまでやって、ようやく気がついた。

2番目や3番目のfunc1のように、クラスのメソッドにした場合はなぜにメソッドが呼ばれるまで実行されないのか? それは極単純に「member……」と書くか「let……」と書くかの違いに応じて、扱いが変わっているのではないか? わからんけど。

だから、4番目の例では、newしたタイミングでlet束縛の「printf "CTest.func1\n"」が実行されて、「c.func3」は無視されていると思われる。

5.まとめ

引数なしの「member……」と「let……」の扱いが相違するのはなんとなく直観に反する気もするけど、とりあえず、引数なしの関数にはダミーの引数であるunit値を指定させたほうがいいらしい。

少なくともそうすれば、定数のつもりなのか、引数なしの関数のつもりなのかが明らかになるし、関数が実行されるタイミングを間違えることもなくなるだろう。