読者です 読者をやめる 読者になる 読者になる

テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

簡単なストレージテストツールmio(mirror IO)

中長期的に, Rustに取り組んでいこうと思ったのは本当だ. 実際にこの一週間ほど, かなりの時間を投資した. でも, 諦めようと思う.

Rustに取り組んでいたのは, Rustが明らかに素晴らしい言語だということと, その言語でフリーランス案件をとれるようになりたいというモチベーションからだが, 私には手に負えないという結論に至った. 寿命とか所有権というRustの特長については, 足かせにしか見えなくなってきた. ベクターの中の値を参照しようとしたらmoveがどうとかと怒られた時, 私の中の糸はぷつんと切れた. Rustについては, ゴミだとか悪態をつくつもりはない. ただ私にはRustを操るに至るだけの頭脳がなかった. 今は劣等感で, 涙が自然とあふれてくる. Rustを流暢に書く各位には, 尊敬申し上げる.

本当は, ライトブーストのツールをRustで作ると宣言していたのだが, これはドミトリにパッケージ化してもらうことを目標とするので, 妥協してGoにした. せめてもの償いとして, mioという, 簡単なストレージテストツールを作ろうと思っていた.

mioは, 「ストレージソフトウェアはまじで複雑化しており, 簡単なテストでも痒いところに手が届けば役に立つ」という, 私のライトブースト開発の経験を元にして考案された. ストレージは, 階層化されており, 制御は極めて複雑になっている.

原理は簡単であり, テスト対象のデバイスAと別のデバイスBを用意して, ライトをミラーリングし, リード時にAとBのデータが等しいか調べるというものである. すでに同様のものは存在する可能性は高いが, 使いやすさやデバグ支援機能などで差別化をしていければ良いと思っていた.

Rustに挫折した私は, Haskellに回帰した. もともとHaskellには, 相当な投資をしており, 過去にもいくつか記事を書いている. ScalaにはScalazという関数型ライブラリがあり, これはHaskellをベースにしているから, Scalaで仕事をしていく手前, Haskellを積極的に書いていくのは相乗効果があり, 都合がいい. そろそろ, Haskellをメイン言語として使っていく時期かなとは思っていた. それで, mioをHaskellで書くことにした.

実装は2時間ほどで終わった. 瞬殺だった.

akiradeveloper/mio · GitHub

import System.Environment
import Text.Regex
import System.IO
import Control.Monad
import Data.Bits
import Data.ByteString
import System.Random
import Data.Word

data Direction = R | W deriving Show               
type IOLine = (Direction, Int, Int)

split :: String -> IOLine
split s = 
    let [a,b,c] = splitRegex (mkRegex ",") s in
    (case a of
       "R" -> R 
       "W" -> W,
     read b :: Int,
     read c :: Int)

randomByteString n g = pack $ randomBytes n g
  where randomBytes 0 _ = []
        randomBytes n g = fromIntegral val:randomBytes (n-1) nextG
          where (val, nextG) = next g
-- randomByteString n g = undefined

main = do
    [o, m] <- getArgs
    lines <- fmap (fmap Main.split . lines) System.IO.getContents
    origH <- openFile o ReadWriteMode
    mirrH <- openFile m ReadWriteMode
    forM_ lines $ \(rw, start, len) -> do
      case rw of
        R -> do
          hSeek origH AbsoluteSeek (toInteger $ start `shiftL` 9)
          origDat <- hGet origH (len `shiftL` 9)
          hSeek mirrH AbsoluteSeek (toInteger $ start `shiftL` 9)
          mirrDat <- hGet mirrH (len `shiftL` 9)
          if origDat == mirrDat then return () 
                                else print "read fail"
        W -> do
          g <- getStdGen
          dat <- return $ randomByteString (len `shiftL` 9) g
          hSeek origH AbsoluteSeek (toInteger $ start `shiftL` 9)
          hPut origH dat
          hSeek mirrH AbsoluteSeek (toInteger $ start `shiftL` 9)
          hPut mirrH dat
          return ()

Haskellは, 道がかなり整備されていて, 彼らはとても論理的なので, ヒットする文献も納得に値するものであることが多い. いつか, Haskellフリーランスの案件をとりたいと思う. もしかしたら, もっと大規模なストレージテストツールを計画して, Haskellで実装するかも知れない.