2013/03/20

バージョン情報の作成

Visual StudioでWin32アプリケーションを作るとき、Express版では実行ファイルのバージョン情報を作成する機能が省かれているが、これを手動で作成する方法。

1. 前置き

対象はVisual Studio Express 2012 for Windows Desktopで、Visual C++でWin32コンソールアプリケーションを選んだ場合。C#やVisual Basicの場合は標準でバージョン情報が付くので関係ない。

バージョン情報とは実行ファイルのプロパティを開いたとき「詳細」タブに表示されるもので、この有無はプログラムの実行には関係ないが、何のプログラムか分からなくなったときにその素性を知る手掛かりになる。というより、素性が不明の実行ファイルをいきなり実行するのは普通に考えて危険なので、そういう危険かもしれないファイル扱いされないためには、バージョン情報を付けておくのがベターという話。

2. 作成方法

テキストファイルをプロジェクトに追加するだけなので、そんなに難しくない。

2.1. リソーススクリプトの追加

リソーススクリプトとはバージョン情報などの情報を記述したテキストファイル。Win32コンソールアプリケーションの場合は自動的には作成されないので、追加する必要がある。この例ではプロジェクト名を「Nameless」、リソーススクリプト名を「Nameless.rc」とする。

ソリューションエクスプローラー -> リソースファイル -> 追加 -> 新しい項目 -> ユーティリティ -> テキストファイル(.txt) と進み、ファイル名を「Nameless.rc」と編集して追加。

2.2. リソーススクリプトの編集

作成されたNameless.rcのコードを表示して、以下のように編集する。
#include <windows.h>

VS_VERSION_INFO    VERSIONINFO
FILEVERSION        0,1,0,0
PRODUCTVERSION     0,1,0,0
FILEFLAGSMASK      VS_FFI_FILEFLAGSMASK
FILEFLAGS          0x0L
FILEOS             VOS_NT_WINDOWS32
FILETYPE           VFT_APP
FILESUBTYPE        VFT2_UNKNOWN
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "000004b0" // Neutral language, Unicode
        BEGIN
            VALUE "CompanyName",      ""
            VALUE "FileDescription",  "Win32 console application"
            VALUE "FileVersion",      "0.1.0.0"
            VALUE "InternalName",     "Nameless.exe"
            VALUE "LegalCopyright",   "Copyright (c) 2013 Nameless man"
            VALUE "OriginalFilename", "Nameless.exe"
            VALUE "ProductName",      "Nameless application"
            VALUE "ProductVersion",   "0.1.0.0"
        END 
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x0, 1200 // Neutral language, Unicode
    END
END
それぞれの意味はMSDNのページ(VERSIONINFO resource)に網羅されている。

とくに説明が必要な点としては、
  • VS_FFI_FILEFLAGSMASK、VOS_NT_WINDOWS32、VFT_APP、VFT2_UNKNOWNの部分は直接数字(Long)で指定することも可能で、その場合は冒頭のwindows.hのincludeは不要。
  • 7行目のFILEFLAGSの0x0Lはリリース版の意味。
  • 14行目の「BLOCK "000004b0"」と28行目の「VALUE "Translation", 0x0, 1200」は対の関係にあって、前者の上4桁「0000」と後者の「0x0」はlangID、前者の下4桁「04b0」と後者の「1200」はcharsetIDを示す。この例ではlangIDは指定なし、すなわちニュートラル言語で、charsetIDはUnicodeの意味。
2.3. ビルド

後はプロジェクトのビルド時にリソーススクリプトのコンパイルとリンクもVisual Studioが自動的にやってくれるので、何もなし。

この例では実行ファイルの「詳細」タブは以下のようになる。

2013/03/15

HD Tuneのぎざぎざの評価

HD Tuneのぎざぎざの形は偽のものだとして、これをどう捉えるか。

(このエントリは一続きのエントリの2/2)

2.1. Partial testとFull test

Partial testのぎざぎざが偽のものだとしても、直ちにPartial testはダメで、Full testの方がいいとも言い切れない。この点は自分も逆に考えていた。

なぜFull testでは乱れの少ないきれいなチャートになるかというと、比較的大きなサイズの計測結果からまとめて計算することで、その間の動きをすべて平均化してしまうから。例えば1TBのHDDをFull testで計測すると、200等分の5GBごとにまとめて計算することになる。

こういう平均化は小さくランダムな動きをならして安定的な値を得るには役立つが、記録面の波形はDisk Gazerで見られるように画然として存在するし、その高さも幅も決して小さなものではない。HD Tuneのように位置ごとの速度を示すよう設計されたベンチマークで、波形を押し潰すようにして平均化することが果たして正しいか。

むしろ、チャートの各位置の範囲に含まれる速度の幅をなるべくそのまま表示した方がいいように思う。図にすると、

左側のような一本の線より、右側のような太さのある帯のイメージ。

結局は使う人が何を見たいかによるが、Partial testもその性格を理解して使うなら(という前提は往々にしてスルーされるものだが)、速度の幅をある程度示すものとしてアリではないかと思う。

2.2. Partial test中の違い

という前提でPartial testについて改めて考えると、5段階あるPartial testの各計測点におけるテストサイズは以下のようになっていた。
Fast側から
各計測点における
速度との比
平均
概数
1
13.0%
1/8
2
25.5%
1/4
3
50.5%
1/2
4
100.5%
1
5
200.6%
2

比は4段目を中心として2の倍数になっているが、1段目などはかなり小さい。

これが結果にどう影響するかというと、7K1000で段を変えながら計測すると以下のようになる。
Travelstar 7K1000: HD Tune Pro (Partial test)

段が低いとぎざぎざが激しく、段が高くなるにつれなだらかになるのが分かる。

このどちらの方がいいかとなると、なだらかになるのはテストサイズが大きくなる分、面の間に掛かりやすくなって双方の面の中間の値になる、すなわち双方ともの本来の値から乖離するということだから、実際の速度の幅を忠実に示すという観点からは、逆にテストサイズが小さい低い段の方が、面の本来の値を伝える計測点が多くなって望ましい、と考えることができる。

2.3. まとめ

HD Tuneのぎざぎざの形は偽のものだが、その点を理解して使うなら、むしろPartial testの、その中でもより粗い低い段の方が結果的に実際の速度を忠実に示すので望ましい、という一見転倒した結論になった。我ながら予想外。

HD Tuneのぎざぎざの理由

HD TuneのBenchmarkがAdaptive FormattingのHDDでぎざぎざを描く理由について、記録面の波形によるものと推測してきたが、その結論。

(このエントリは一続きのエントリの1/2)

1.1. HD TuneのBenchmarkの計測方法

他のソフトの動作を外から分析するのはあまり行儀がいいとは言えない気がするが、これを確認しないと先に進めないので、HD Tune Pro(4.01)がBenchmarkを実行中にどうアクセスしているかをProcess Monitorで見てみた。対象はTravelstar 7K1000で容量は1TB。設定はPartial testで5段階中のAccurate側の4段目(デフォルト)、Block sizeは1MiBに設定してリード。

これは開始時で、この後ずっとReadFile(Win32でリードするAPI)が続いていくが、このDetailにリードした位置とサイズが出ている。Offsetが先頭からの距離、すなわち位置で、Lengthがサイズ。単位はByte。

初めに位置0でサイズが512Byte、すなわち1セクタのリードをしている。設定と違うので何かと思ったが、計測位置をジャンプさせる度に初めは同様に512Byteのリードをしているので、これはたぶんHDDをシークさせるためだけのリードで、速度の計算には入れてないのだろうと思う。

これに続いて1048576Byte=1MiBのリードが、隙間なくシーケンシャルに行われている。

結果をまとめると、少し戸惑わせることが分かった。
  1. 計測したサイズ(1MiB×リード回数)は計22250MiBで、容量の2.3%。まあそんなものか。
  2. 計測点の数は200で、各計測点の開始位置は容量を単純に200等分したもの(0、5GB、10GB……)。これはログから予想できたこと。
  3. 各計測点のサイズは一定ではない。……何コレ。
速度を計算するには比が分かればいいのであって、一定のサイズにする必然性はないが、計測条件はなるべく揃えるものじゃないかと思いつつ眺めていたら、気づいた。各計測点のサイズは、その計測点における速度に比例している。

各計測点における速度とテストサイズの関係をまとめたのが以下。速度はMB/sに、テストサイズはMBに、位置は都合でGiBに換算してある。

ほぼ完全に一致している。意図はよく分からないが、たぶん計測しながら速度を見て後何回リードするか決めているのか、予め決めた時間内だけリードを繰り返すようにしているのだと思う。

ちなみに、X25-M G2を5段階中の5段目で計測したときはテストサイズは381MiBで一定だったので、上限はあるっぽい。

1.2. 計測点をDisk Gazerと比較

とにかくHD Tune Proがリードした位置とサイズは分かったので、先頭から40個の計測点について、その位置の波形をDisk Gazerで計測したものと比較してみる。

左側がHD Tune Proのログから抜き出したもので、赤点が各計測点。右側のDisk Gazerのチャートで計測点に当たる部分を赤枠で囲ってある(数が多いので、スライドさせながら見てもらうといいと思う)。

一目瞭然だが、HD Tune Proの値は計測点が波形のどの部分にかかっているかで決定されているのが分かる。荒れた海を走る船のごとく、高い面に乗れば高く、低い面に落ちれば低く、面の間にまたがったときはその割合に応じて、上下している。

これがHD Tuneのぎざぎざの理由、ということになる。

各計測点における値は、その位置とサイズで得られた値として間違ってはいないが、それらを結んだチャートの形は、そのとおりに実際の速度が変動しているわけではないという意味で、偽のものと言えると思う。

次に、これをどう評価するかについて。

2013/03/14

Disk Gazer

120%趣味で作ったソフトです。

1. 概要

物理的ディスクのシーケンシャルリードの転送速度を細かい単位で、かつ位置を問わずに計測するためのベンチマークツールです。というより、HDDの記録面の波形を見るためのソフトと言った方が正しいですが。HD Tune Proよりもきめ細かく(1MiB以下)、HD Tune Proでは見られなかった先頭以外の波形も確認できるのがポイントです。

現在のHDDは、2.5インチHDDでも最外周のトラック当たり容量は1MiBを超えるので、トラック1本と同じか小さいぐらいの単位で計測できることになります。

リード方法はhiyohiyoさん作のCrystalDiskMark(3.0.2)のシーケンシャルリードテストをベースにしています。ただし、Disk Gazerは物理的ディスクをファイルシステムを使わずにリードすること、Block size(一度にリードする量)ごとに時間を記録して速度を計算するなどの違いがあります。

そもそも途中の計算順序や端数処理で結果が微妙に変わってくるのがコンピューターの計算なので、近い値にはなっても必ずしも一致はしません。最終的に表示されたものが、そのベンチマークにおける値ということで。

といっても、Disk Gazerの場合、計測単位が小さい関係上、最大値(Max)も最小値(Min)も瞬間的に出ただけの値になるので、あまり意味はありません。また平均値(Avg)も、波形の前ではあまり参考にはなりません。波形そのものを見るためのものです。という意味で、ベンチマークと呼ぶのは正しくない気もしますが……。

実用的な面では、代替セクタになっている位置が分かるかもしれません……。

細かいことは、興味があればreadmeを見てください。

[追記]

Disk Gazerを拡張した話を書いたので、実行ファイルとソースコードはそちらから。

2. Travelstar 7K1000

Disk Gazerのテストを兼ねてHGSTの7200RPMのTravelstar 7K1000を買ったので、まず定点観測的に。

左側が7K1000、右側が5K1000の1TBモデル。
7k1000-5k1000-1

ラベル以外の外見は、回転数が違うにもかかわらずPCBを含めて全く同じ。一方、重量は5K1000が100gなのに対して、7K1000は112gと重い。回転音はそれと意識するほどの差は感じない。

ラベルは日立の会社名が抜けて、略称だったHGSTがそのまま会社名になっている。5Vの消費電力が5K1000の700mAから800mAに増えているのが、回転数の差を反映している。

CrystalDiskInfoで見たところ。バッファサイズが32MB以上になっている。
7k1000-cdi52-en

先頭10GBにパーティションを作成し、ThinkPad X61s上のWindows 8からCrystalDiskMarkで計測。
Travelster 7K1000: CrystalDiskMark

シーケンシャルアクセスでは5K1000が114MB/s程度だったので、7K1000は138MB/s程度で21%増と、HDDとしては満足すべき速度向上だと思う。

次にHD Tune Pro(4.01)のBenchmarkで全領域を通して見たところ。Block sizeは1MiBに設定。
Travelstar 7K1000: HD Tune Pro (Full and Partial test)

HD Tune ProはWindows 8上ではウィンドウ内の部品のサイズ調整がうまく行かないらしく(5.0でも同様)、日本語表示だとはみ出してしまうので英語表示にしたら、今度は小さすぎる……が、そこは措く。

結果はいつものHD Tune Proで、CrystalDiskMarkより値が高めなのも従来どおり。

ランダムアクセスはこんな感じ。
Travelstar 7K1000: HD Tune Pro (Random access)

リードを見る限り、回転数相応か5K1000より少しだけ向上している。

さて、記録面はどうかというと以下のとおり。
Travelstar 7K1000: HD Tune Pro (Short stroke)

4つの面が出ている。2GBの結果を見ると、
Travelstar 7K1000: HD Tune Pro (Short stroke)

かなりはっきりした波形で、各組の長さは620MBといったところ。5K1000が667MBだったので、少し小さい。

SpecificationにあるCylinder allocationから計算すると、最外周のゾーン0のトラック当たり容量は、5K1000が約1.17MiBなのに対して、7K1000は約1.13MiBで少し小さいが、典型的な例として示されているだけなので直結はしない。

3. テスト

この7K1000と5K1000の1TBモデルがDisk Gazerでどう見えるかテストしていく。

それぞれの先頭を、領域のサイズ(Area)を0.5GiBと1GiBに設定して計測。なお、チャートの単位はY軸が速度(MB/s)で、X軸が位置(MiB)。

びっしり剣山のように上に突き出している部分は、位置も高さも再現性があるので単純な計測上のノイズではないが、とりあえず措くとして、波形自体は極めてクリアに出ている。カメラのピントが合ったというか、これが本来の波形で、HD Tune Proで見えるものは、あれはあれで鈍っているのだと思う。

さらに、領域のサイズを1GiBで、位置(Location)を中央と末尾にして計測したものを重ねて表示すると(水平移動させるので本来の位置とは違う)以下のようになる。

位置が後ろに行くにつれ、波形が形を変え、全体的に低く短くなっていくのが捉えられている。

面から針のように出ている部分も変わっているが、この正体を探るため、ThinkPad X60sでも計測してみる。位置は先頭で、領域のサイズは0.5GiB。

5K1000は依然剣山になっているが、7K1000は135MB/s当たりより上には出ず、水平になっている。これには単純な理由があって、X60sはSATA 1.5Gb/sなので、この当たりがバスの実効上の上限になっていて、それに引っ掛かっている。

見方を変えると、バスの上限でカットされるということは、針のような部分が起きているのはバスの向こう側、つまりPC本体側ではなくHDD側ということになる。となると、HDDの内部で起きていることなど追求しようがないが、Disk GazerのBlock Offset(readme参照)を使えば、何とかならなくもない。

簡単に言うとBlock Offsetを使えば計測上の偽の値を選別できる、と期待されるので、X61sに戻ってBlock Offsetを1/16に設定し、改めて計測してみた。

結果は、中央と末尾ではBlock Offsetがよく効いて、記録面が切り替わるときの谷もはっきり出ている。一方、先頭では一定の高さで残っている。

これは針のように値が高くなる位置が完全には固定されておらず(固定されていれば、記録面が切り替わるときの谷のように高さは変わらない)、リードの開始位置によって位置が微妙に変わることを示唆しているが、値が高くなる部分が存在することは変わらない。いずれにせよ、これ以上の追求は難しい。

4. 残っていた問題

続いて、記録面に関して当てになる道具がないがゆえに残っていた問題について、Disk Gazerを使って再度トライしてみる。

4.1. Travelstar 5K1000-500

HD Tune Proで先頭を見て確認できた水平線の高さは2段階だけだったので、先頭以外はどうなっているのかDisk Gazerで見てみる。ThinkPad X61s上のWindows 8から先頭、中央、末尾の1GiBの領域を計測し、重ねて表示したところ。

中央と末尾では1つの水平線の高さがずれて3段階になっている。記録面が切り替わるときの谷もはっきり出ているし、4記録面だと改めて確認できた。

4.2. Travelstar 5K500.B-500

Iometerを使った方法では途中から値がおかしくなったので、これも同様に見てみる。ThinkPad X60s上からで、まず5K500.B-500aの方。

波形が途中で変わっているのがはっきり見て取れる。先頭では針のように高くなる部分はまだらな一方、中央では下に向かって多数出ているので、これが機種とディスク中の位置に依存していることが窺える。

次に5K500.B-500bの方。これはHD Tune ProとIometerで確認できた水平線が同じ長さで2段階の高さの2つだけだったので、どういう面の構成になっているか判別できなかった。

先頭ではそれぞれの水平線の真ん中に規則的に現れる谷があるが、中央と末尾でははっきりしない。そこでBlock Offsetを1/8に設定して再度計測してみた。

これでようやく記録面が移り変わるときの谷がそれぞれの水平線の真ん中に確認できた。したがって、最初から最後までゾーンを通して同じ記録密度の記録面が2組ある4記録面の構成だと言える。

4.3. Momentus 5400.5-320

これもIometerでは途中から値がおかしくなったので。

DiskSpeed32の結果から見当は付いていたが、後方に行くにつれ波形が同じ形のままミニチュアのように小さくなっていくのが分かる。

4.4. Scorpio WD2500BEVS

これはIometerを使う方法では全く歯が立たなかった。

中央では明らかに先頭から波形が変わっているのが分かる。鏡像反転でないことといい、HGSTに近い。

4.5. Momentus 5400.3PSD

HD Tune Proの結果から構成を推測してみたが、あまり確信はなかった。

中央で1つの水平線の高さがずれて3段階となり、推測したとおりの鏡像反転であることがはっきりした。

一方、先頭、中央、末尾に共通して、鏡像反転するときは記録面の移り変わりの谷が見えないが、それ以外のときは谷がはっきり見えている。これは鏡像反転するときは同じ記録面上でそのまま移動するだけだから時間はかからないと考えれば矛盾はしない、というか鏡像反転を裏付けるものだと思う(5400.5では谷が出ているが……)。

5. まとめ

以上、Disk Gazerが記録面を見るための道具として使えることは確認できた。これがあれば記録面に関するたいていの問題には答えを見つけられるのではないかと思う。