ラベル SSD の投稿を表示しています。 すべての投稿を表示
ラベル SSD の投稿を表示しています。 すべての投稿を表示

2014/10/05

ThinkPad X230とmSATA SSD

ThinkPad X230にmSATAのCrucial M550 256GBを入れた。
ThinkPad X230 and Crucial M550
ThinkPad X230 and Crucial M550

開発環境を色々入れて手狭になってきていたところに、Windows 10 TPをどうやって動かそうか考えて、元からmSATAに増設する予定だったので丁度よく。

Windows 10 TPのインストールはISOファイルからインストール用USBメモリを作って行ったが、X230をUEFIブートにしているので、USBメモリもUEFIブータブルにするためにFAT32でフォーマットする必要があった以外は従来と変わりない。

とりあえずインストールしたままの状態ではM550の温度は常に50度台前半で、かつてないペースで雫ちゃんの声を聞くことになった。

さすがに気になったので、IntelのChipset SupportとRapid Storageのドライバーを古いインボックスのものからLenovoの新しいものに代えたら、30度台後半で落ち着くようになった。

速度はmSATAの制限があるので、このぐらい。実用上は十分以上。

これでまたX230のスロットが一つ埋まった。

2014/04/30

SSDかどうかをWMIから判別する

SSDかどうかをC#から判別するではP/Invokeを使ったが、それよりハードルの低いWMIでもSSDかどうかを判別する方法はある(ことを知った)。

1. 説明


具体的には、WMIからWindows Storage Management APIにあるMSFT_PhysicalDiskクラスを利用する。ただし、このWindows Storage Management APIが使えるのはWindows 8(とWindows Server 2012)以降なので、完全にこれに頼れるものでもなく、ケースバイケースで。なお、管理者権限は不要。

初めにWMIでディスクのハードウェア的な情報を取得できるものとして、新しいMSFT_DiskMSFT_PhysicalDisk、および従来からあるWin32_DiskDriveのプロパティをざっくり比較してみた。
この中でMSFT_PhysicalDiskのSpindleSpeedとMediaTypeにSSDの情報が含まれている。
  • SpindleSpeed
    文字どおりディスクの回転数で、これが0であればSSD。HDDで回転数の情報が取れればその回転数(RPM)、そうでなければUInt32の上限値が返ってくる。
  • MediaType
    これが3であればHDD、4であればSSD。情報が取れなければ0が返ってくる。
ここまで分かれば、後は名前空間が従来の\root\CIMV2ではなく、\Root\Microsoft\Windows\Storageなので、それを明示的に指定する必要がある以外は従来のWMIと変わりない。

2. テスト


テスト用に作成したC#のコンソールアプリを、ThinkPad X230上のWindows 8.1で実行した結果。

1番目はUSBポータブルケースに入れたTravelstar 5K1000で、USB接続ではMediaTypeもSpindleSpeedも情報を取れなかった。2番目はUSBメモリで、これも情報を取れず。3番目は内蔵SSDで、これはMediaTypeとSpindleSpeedの両方でSSDという情報が取れた。

次にThinkPad X61s上のWindows 8で実行した結果。

1番目は内蔵HDDのTravelstar 7K1000で、MediaTypeはHDDという情報が取れたが、SpindleSpeedはなぜか情報が取れなかった。2番目と3番目のUSBメモリは両方取れなかった。

以上、とりあえず内蔵であればSSDかどうかの判別に使えると思う。

[追記] PowerShellから実行

WMIということは当然PowerShellからも実行できるわけで、例として以下のような感じ。
Get-WMiObject -namespace Root\Microsoft\Windows\Storage -class msft_physicaldisk | Select-Object FriendlyName,Model,MediaType | Sort-Object FriendlyName

これを実行したもの。MediaTypeが3であればHDD、4であればSSD。

問題なく取得できている。

3. BusType


SSDに限らないが、BusTypeについて、従来のWin32_DiskDriveのInterfaceTypeプロパティでは取れる情報が少なかったので、Win32のDeviceIoControlをIOCTL_STORAGE_QUERY_PROPERTYで実行してSTORAGE_BUS_TYPEを取得するようにしていたが、MSFT_DiskとMSFT_PhysicalDiskにはBusTypeプロパティがあるので、比較してみた。
一目瞭然だが、情報はほとんど同じで、MSFT_DiskがNVMeを取れるだけ優位にある。したがって、BusTypeに関しては条件が許せばMSFT_Diskで代替できると思う。

2012/12/21

ReadyNASにSSD

大容量SSDの価格低下もそこそこ進んでいるので、先々はNASにもSSDを入れることを考えて、ReadyNAS Ultra 2にIntel X25-M G1を入れてみるテスト。

1. SMART


HDDと入れ替えると、HDDと同様にRAIDiatorがインストールされて(X-RAID2を指定)普通に起動。FrontViewからSSDの情報も見られる。
Intel X25-M in FrontView

温度は1C/33Fと出ているが、RAIDar Protocolで返ってくるのを見ると-1C/31Fで、食い違っていた。

ここからSMARTも一応表示される。
Intel X25-M SMART in FrontView

が、この中に温度はない。また、寿命に関係するAvailable Reserved SpaceとMedia Wearout Indicatorは項目には出ているが、正しい値は取れてない。

このSMARTはPCに接続してCrystalDiskInfo、SSD Toolbox、Smartmotoolsで見たときには、それぞれこんな感じ。
Intel X25-M SMART by CrystalDiskInfo
Intel X25-M SMART by SSD Toolbox
Intel X25-M SMART by Smartmontools

温度


先に温度について考えると、一見して明らかなように、このSSDはSMARTのデータに温度(IDは16進数でC2、10進数で194)を含んでいない。SSDの中には0Cと返すものもあるようだが、このSSDはそもそも温度のデータを返さない。

したがって、ReadyNASが示す1C/33Fあるいは-1C/31Fはダミーの数字で、それもたぶん-1C/31Fの方が本来の数字で(コードの世界では該当するものが存在しないときに-1を返したりする)、その摂氏のマイナス符号を認識し損ねて1Cと取った上で華氏をそれに合わせて計算したのが1C/33Fではないか、という気がする。

寿命


意外だったのはReadyNASがIntelのSSDに特有のAvailable Reserved Space(E8)とMedia Wearout Indicator(E9)を認識したことで、このIDが示すもののデータを持っていなければこの名前は出てこないはず……。

と、ReadyNASではたぶん字数を減らすために「e」を抜いて「Available Reservd Space」となっているが、上にある「Reallocated Sector Count」は字数が多いにもかかわらずそのままで、少し不自然。一方、この「Available Reservd Space」はSmartmontoolsの表記と同じで、「Intel Internal」も同じ。ということから、ReadyNASは標準的な項目以外はSmartmontoolsと同じデータを利用しているのではないか、という推測を立て得る。

それはともかくとして、値の方は出してくるものを間違えていて、意味を成してないわけだが。この当たり、各ベンダー独自の仕様に合わせてデータを処理するようにしないと意味のある数字は拾い出せない、という当然のことを示している。

2. 評価


NASの動作としてはごく普通で、スピンダウン時でもスピンアップを待つことなくすぐにアクセスできる(SSDの場合にスピンダウンが実際にどう動いているのかは未確認)。

という意味で普通に使う分には問題なさそうだが、SMARTの監視は実質的にできず、各ベンダーの仕様がばらばらである限り、NAS側の対応もなかなか進まないような気がするので(add-onでも出てくれば別だが)、SSDの状態が気になるなら時々外してPCに接続してチェックするしかないと思う。

[追記1]

そういえばSmartmontoolsはたいていのLinuxディストリビューションに含まれている……ことを思い出して、ReadyNASのSSHアクセスを有効にしてログインすると、しっかりRAIDiatorにも入っていた。

これでSMARTを見てみると、PCとの接続時と同じように表示される。
Intel X25-M SMART by Smartmontools on RAIDiator (Linux) through SSH

したがって、ReadyNASに入れたままでも、これで定期的にチェックするようにすればSMARTの値を監視できることになる。

以上、後はしいて言えばTrimがどうなるかという点を除けば、ReadyNASでSSDを使う上での障害は実質的になさそうということが分かった。

[追記2]

WindowsのクライアントPCからSMARTの値をチェックするためのスクリプトを書いてみた。PuTTYを使ってSSHアクセスし、smartctlを実行して、結果からSMARTの目的の項目を拾い出してCSV形式で保存する。

手順としては、
  1. ReadyNASに「Enable Root SSH Access」Add-onをインストールしてSSHアクセスを可能にする。
  2. PuTTYをダウンロードして適当なフォルダーに置く。使うのはコマンドライン用のPLINK.EXE。
  3. 以下の内容のバッチファイルを作成して、ファイル名はここでは「smartctl.bat」として同じフォルダーに保存する。
    plink nas-XX-XX-XX -l root -pw netgear1 ^
     "smartctl -A -f brief /dev/sda" > result.txt
    
    • nas-XX-XX-XXはReadyNASのホスト名かIPアドレス
    • -pwの後ろは管理者パスワード
    • /dev/sdaは1番目のディスクの意味

  4. 以下の内容のVBScriptを作成して、ファイル名はここでは「checksmart.vbs」として同じフォルダーに保存する。ATTRIBUTESで目的の項目を指定。
    Option Explicit
    
    Dim FILE_BAT 'Batch file to execute smartctl through SSH
    Dim FILE_RLT 'File to store result of smartctl temporarily
    Dim FILE_RCD 'File to record (append) result of smartctl
    FILE_BAT = "smartctl.bat"
    FILE_RLT = "result.txt" 'Must be the same file in batch file
    FILE_RCD = "record.csv"
    
    Dim ATTRIBUTES 'SMART attributes (separated by space)
    ATTRIBUTES = "Available_Reservd_Space Media_Wearout_Indicator"
    
    'Execute smartctl through SSH
    Dim objShell
    Set objShell = WScript.CreateObject("WScript.Shell")
    Dim result 'Return value to avoid error in using Run method
    result = objShell.Run(FILE_BAT, 0, True)
    Set objShell = Nothing
    
    'Process result of smartctl
    Dim strBuf
    
    Dim objFSO
    Dim objFile
    Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.OpenTextFile(FILE_RLT)
    strBuf = objFile.ReadAll
    Set objFile = Nothing
    Set objFSO = Nothing
    
    Dim strLines
    strLines = Split(strBuf, vbLf)
    
    Dim strSer 'Array to hold names of attributes
    strSer = Split(ATTRIBUTES)
    
    Dim strVal 'Array to hold values of attributes
    ReDim strVal(UBound(strSer))
    
    Dim objRegExp
    Set objRegExp = New RegExp
    objRegExp.Pattern = " \d{3} " 'Pattern of value of attributes
    objRegExp.IgnoreCase = True
    objRegExp.Global = True
    Dim i
    Dim j
    For i = 0 To UBound(strLines)
        For j = 0 To UBound(strSer)
            If 0 < InStr(1, strLines(i), strSer(j), 1) Then
                Dim objMatches
                Set objMatches = objRegExp.Execute(strLines(i))
                If 0 < objMatches.Count Then
                    strVal(j) = objMatches(0).Value
                End If
                Set objMatches = Nothing
            End If
        Next
    Next
    Set objRegExp = Nothing
    
    'Record result of smartctl
    Dim strRec
    strRec = Now() & ","
    For j = 0 To UBound(strVal)
        strRec = strRec & Trim(strVal(j)) & ","
    Next
    
    Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
    If Not objFSO.FileExists(FILE_RCD) Then
        'If first record, add header line
        strRec = "Date," & Join(strSer, ",") & "," & vbCrLf & strRec
    End If
    Set objFile = objFSO.OpenTextFile(FILE_RCD, 8, True)
    objFile.Write(strRec & vbCrLf)
    Set objFile = Nothing
    Set objFSO = Nothing
    
    (smartctl.batの内容をFILE_BATの部分に直接書いても良さそうなものだが、そうするとなぜかrecord.txtがホスト側に作成されてしまうので、分けた。)
これで、このchecksmart.vbsを定期的に実行するように設定すれば、結果がCSVファイルに記録されていく。

2012/11/06

SSDかどうかをC#から判別する

ある物理的なドライブがSSDかどうかを判別する方法は色々あり得るが、Microsoftが示したアルゴリズム(Windows 7 Disk Defragmenter User Interface Overview)にしたがってNyaRuRuさんがC++のコードを書かれていたので(SSDなら動作を変えるアプリケーションを作る)、同じことをC#からWin32を使って行うコードを書いてみた。

内容的にはほぼNyaRuRuさんのコードのままで、以下の方法の2本立て。
  • Windows 7以降で使えて、管理者権限が不要な「no seek penalty」を利用する。
  • それ以前のOSでも使えるが、管理者権限が必要な「nominal media rotation rate」を利用する。
まずWin32の宣言は以下のとおり。使用するWin32の関数はCreateFileとDeviceIoControlで、後はそれに必要な定数と構造体。
// For CreateFile to get handle to drive
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;

// CreateFile to get handle to drive
[DllImport("kernel32.dll", SetLastError = true)]
private static extern SafeFileHandle CreateFileW(
    [MarshalAs(UnmanagedType.LPWStr)]
    string lpFileName,
    uint dwDesiredAccess,
    uint dwShareMode,
    IntPtr lpSecurityAttributes,
    uint dwCreationDisposition,
    uint dwFlagsAndAttributes,
    IntPtr hTemplateFile);

// For control codes
private const uint FILE_DEVICE_MASS_STORAGE = 0x0000002d;
private const uint IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE;
private const uint FILE_DEVICE_CONTROLLER = 0x00000004;
private const uint IOCTL_SCSI_BASE = FILE_DEVICE_CONTROLLER;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;
private const uint FILE_READ_ACCESS = 0x00000001;
private const uint FILE_WRITE_ACCESS = 0x00000002;

private static uint CTL_CODE(uint DeviceType, uint Function,
     uint Method, uint Access)
{
    return ((DeviceType << 16) | (Access << 14) |
    (Function << 2) | Method);
}

// For DeviceIoControl to check no seek penalty
private const uint StorageDeviceSeekPenaltyProperty = 7;
private const uint PropertyStandardQuery = 0;

[StructLayout(LayoutKind.Sequential)]
private struct STORAGE_PROPERTY_QUERY
{
    public uint PropertyId;
    public uint QueryType;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)]
    public byte[] AdditionalParameters;
}

[StructLayout(LayoutKind.Sequential)]
private struct DEVICE_SEEK_PENALTY_DESCRIPTOR
{
    public uint Version;
    public uint Size;
    [MarshalAs(UnmanagedType.U1)]
    public bool IncursSeekPenalty;
}

// DeviceIoControl to check no seek penalty
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl",
   SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeviceIoControl(
    SafeFileHandle hDevice,
    uint dwIoControlCode,
    ref STORAGE_PROPERTY_QUERY lpInBuffer,
    uint nInBufferSize,
    ref DEVICE_SEEK_PENALTY_DESCRIPTOR lpOutBuffer,
    uint nOutBufferSize,
    out uint lpBytesReturned,
    IntPtr lpOverlapped);

// For DeviceIoControl to check nominal media rotation rate
private const uint ATA_FLAGS_DATA_IN = 0x02;

[StructLayout(LayoutKind.Sequential)]
private struct ATA_PASS_THROUGH_EX
{
    public ushort Length;
    public ushort AtaFlags;
    public byte PathId;
    public byte TargetId;
    public byte Lun;
    public byte ReservedAsUchar;
    public uint DataTransferLength;
    public uint TimeOutValue;
    public uint ReservedAsUlong;
    public IntPtr DataBufferOffset;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] PreviousTaskFile;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
    public byte[] CurrentTaskFile;
}

[StructLayout(LayoutKind.Sequential)]
private struct ATAIdentifyDeviceQuery
{
    public ATA_PASS_THROUGH_EX header;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public ushort[] data;
}

// DeviceIoControl to check nominal media rotation rate
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl",
   SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeviceIoControl(
    SafeFileHandle hDevice,
    uint dwIoControlCode,
    ref ATAIdentifyDeviceQuery lpInBuffer,
    uint nInBufferSize,
    ref ATAIdentifyDeviceQuery lpOutBuffer,
    uint nOutBufferSize,
    out uint lpBytesReturned,
    IntPtr lpOverlapped);
これを受けた1つ目のメソッドが「no seek penalty」を利用する「HasNoSeekPenalty」で、物理ドライブ名を「\\\\.\\PhysicalDrive0」の形にした文字列を引数に取る。QA@ITで質問させていただいたもの(SSDかどうかをC#から判別する方法)と基本的に同じ。あまり似た例がなかったので、ほぼスクラッチ。
// Method for no seek penalty
private static void HasNoSeekPenalty(string sDrive)
{
    SafeFileHandle hDrive = CreateFileW(
        sDrive,
        0, // No access to drive
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        IntPtr.Zero,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        IntPtr.Zero);

    if (hDrive == null || hDrive.IsInvalid)
    {
        string message = GetErrorMessage(Marshal.GetLastWin32Error());
        Console.WriteLine("CreateFile failed. " + message);
    }

    uint IOCTL_STORAGE_QUERY_PROPERTY = CTL_CODE(
        IOCTL_STORAGE_BASE, 0x500,
        METHOD_BUFFERED, FILE_ANY_ACCESS); // From winioctl.h

    STORAGE_PROPERTY_QUERY query_seek_penalty =
        new STORAGE_PROPERTY_QUERY();
    query_seek_penalty.PropertyId = StorageDeviceSeekPenaltyProperty;
    query_seek_penalty.QueryType = PropertyStandardQuery;

    DEVICE_SEEK_PENALTY_DESCRIPTOR query_seek_penalty_desc =
        new DEVICE_SEEK_PENALTY_DESCRIPTOR();

    uint returned_query_seek_penalty_size;

    bool query_seek_penalty_result = DeviceIoControl(
        hDrive,
        IOCTL_STORAGE_QUERY_PROPERTY,
        ref query_seek_penalty,
        (uint)Marshal.SizeOf(query_seek_penalty),
        ref query_seek_penalty_desc,
        (uint)Marshal.SizeOf(query_seek_penalty_desc),
        out returned_query_seek_penalty_size,
        IntPtr.Zero);

    hDrive.Close();

    if (query_seek_penalty_result == false)
    {
        string message = GetErrorMessage(Marshal.GetLastWin32Error());
        Console.WriteLine("DeviceIoControl failed. " + message);
    }
    else
    {
        if (query_seek_penalty_desc.IncursSeekPenalty == false)
        {
            Console.WriteLine("This drive has NO SEEK penalty.");
        }
        else
        {
            Console.WriteLine("This drive has SEEK penalty.");
        }
    }
}
(注)GetErrorMessageはエラーメッセージを得るためのメソッド。以下同じ。

2つ目のメソッドが「nominal media rotation rate」を利用する「HasNominalMediaRotationRate」で、引数は同じ。同じようにしてドライブの情報を取得する例は結構あったので(例えば、Getting Hard disk drive info with DeviceIOControl)、かなり参考にさせていただいた。
// Method for nominal media rotation rate
// (Administrative privilege is required)
private static void HasNominalMediaRotationRate(string sDrive)
{
    SafeFileHandle hDrive = CreateFileW(
        sDrive,
        GENERIC_READ | GENERIC_WRITE, // Administrative privilege is required
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        IntPtr.Zero,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        IntPtr.Zero);

    if (hDrive == null || hDrive.IsInvalid)
    {
        string message = GetErrorMessage(Marshal.GetLastWin32Error());
        Console.WriteLine("CreateFile failed. " + message);
    }

    uint IOCTL_ATA_PASS_THROUGH = CTL_CODE(
        IOCTL_SCSI_BASE, 0x040b, METHOD_BUFFERED,
        FILE_READ_ACCESS | FILE_WRITE_ACCESS); // From ntddscsi.h

    ATAIdentifyDeviceQuery id_query = new ATAIdentifyDeviceQuery();
    id_query.data = new ushort[256];

    id_query.header.Length = (ushort)Marshal.SizeOf(id_query.header);
    id_query.header.AtaFlags = (ushort)ATA_FLAGS_DATA_IN;
    id_query.header.DataTransferLength =
        (uint)(id_query.data.Length * 2); // Size of "data" in bytes
    id_query.header.TimeOutValue = 3; // Sec
    id_query.header.DataBufferOffset = (IntPtr)Marshal.OffsetOf(
        typeof(ATAIdentifyDeviceQuery), "data");
    id_query.header.PreviousTaskFile = new byte[8];
    id_query.header.CurrentTaskFile = new byte[8];
    id_query.header.CurrentTaskFile[6] = 0xec; // ATA IDENTIFY DEVICE

    uint retval_size;

    bool result = DeviceIoControl(
        hDrive,
        IOCTL_ATA_PASS_THROUGH,
        ref id_query,
        (uint)Marshal.SizeOf(id_query),
        ref id_query,
        (uint)Marshal.SizeOf(id_query),
        out retval_size,
        IntPtr.Zero);

    hDrive.Close();

    if (result == false)
    {
        string message = GetErrorMessage(Marshal.GetLastWin32Error());
        Console.WriteLine("DeviceIoControl failed. " + message);
    }
    else
    {
        // Word index of nominal media rotation rate
        // (1 means non-rotate device)
        const int kNominalMediaRotRateWordIndex = 217;

        if (id_query.data[kNominalMediaRotRateWordIndex] == 1)
        {
            Console.WriteLine("This drive is NON-ROTATE device.");
        }
        else
        {
            Console.WriteLine("This drive is ROTATE device.");
        }
    }
}
全体を通したコードはこちらに載せた。 Visual Studio 2012で.NET Framework 4.0を対象として作成し、ThinkPad X61sにインストールしたWindows 8 ProとWindows 7上で、SSD(Intel X25-M G2)とHDDを判別できることを確認している。 まあC++のライブラリを作ってそれを利用する形でもいいが、.NETから直接使える方法があってもいいかな、ということで。

[追記] 物理ドライブ名の取得

論理ドライブ名から物理ドライブ名を取得するコードも書いてみた。WMIを使う方法もあるが、折角なのでWin32で。 まずWin32の宣言。
// For CreateFile to get handle to drive
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080;

// CreateFile to get handle to drive
[DllImport("kernel32.dll", SetLastError = true)]
private static extern SafeFileHandle CreateFileW(
    [MarshalAs(UnmanagedType.LPWStr)]
    string lpFileName,
    uint dwDesiredAccess,
    uint dwShareMode,
    IntPtr lpSecurityAttributes,
    uint dwCreationDisposition,
    uint dwFlagsAndAttributes,
    IntPtr hTemplateFile);

// For control codes
private const uint IOCTL_VOLUME_BASE = 0x00000056;
private const uint METHOD_BUFFERED = 0;
private const uint FILE_ANY_ACCESS = 0;

private static uint CTL_CODE(uint DeviceType, uint Function,
                             uint Method, uint Access)
{
    return ((DeviceType << 16) | (Access << 14) |
            (Function << 2) | Method);
}

// For DeviceIoControl to get disk extents
[StructLayout(LayoutKind.Sequential)]
private struct DISK_EXTENT
{
    public uint DiskNumber;
    public long StartingOffset;
    public long ExtentLength;
}

[StructLayout(LayoutKind.Sequential)]
private struct VOLUME_DISK_EXTENTS
{
    public uint NumberOfDiskExtents;
    [MarshalAs(UnmanagedType.ByValArray)]
    public DISK_EXTENT[] Extents;
}

// DeviceIoControl to get disk extents
[DllImport("kernel32.dll", EntryPoint = "DeviceIoControl",
           SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool DeviceIoControl(
    SafeFileHandle hDevice,
    uint dwIoControlCode,
    IntPtr lpInBuffer,
    uint nInBufferSize,
    ref VOLUME_DISK_EXTENTS lpOutBuffer,
    uint nOutBufferSize,
    out uint lpBytesReturned,
    IntPtr lpOverlapped);
これを受けたメソッド。論理ドライブ名の文字を引数とし、始めにリムーバブルディスクなどではない固定ディスクかどうかのチェックを通す。
// Method for disk extents
private static void GetDiskExtents(char cDrive)
{
    DriveInfo di = new DriveInfo(cDrive.ToString());
    if (di.DriveType != DriveType.Fixed)
    {
        Console.WriteLine("This drive is not fixed drive.");
    }

    string sDrive = "\\\\.\\" + cDrive.ToString() + ":";

    SafeFileHandle hDrive = CreateFileW(
        sDrive,
        0, // No access to drive
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        IntPtr.Zero,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        IntPtr.Zero);

    if (hDrive == null || hDrive.IsInvalid)
    {
        string message = GetErrorMessage(Marshal.GetLastWin32Error());
        Console.WriteLine("CreateFile failed. " + message);
    }

    uint IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = CTL_CODE(
        IOCTL_VOLUME_BASE, 0,
        METHOD_BUFFERED, FILE_ANY_ACCESS); // From winioctl.h

    VOLUME_DISK_EXTENTS query_disk_extents =
        new VOLUME_DISK_EXTENTS();

    uint returned_query_disk_extents_size;

    bool query_disk_extents_result = DeviceIoControl(
        hDrive,
        IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,
        IntPtr.Zero,
        0,
        ref query_disk_extents,
        (uint)Marshal.SizeOf(query_disk_extents),
        out returned_query_disk_extents_size,
        IntPtr.Zero);

    hDrive.Close();

    if (query_disk_extents_result == false ||
        query_disk_extents.Extents.Length != 1)
    {
        string message = GetErrorMessage(Marshal.GetLastWin32Error());
        Console.WriteLine("DeviceIoControl failed. " + message);
    }
    else
    {
        Console.WriteLine("The physical drive number is: " +
                          query_disk_extents.Extents[0].DiskNumber);
    }
}
[修正] SafeFileHandleの解放

ドライブへのハンドルの解放にCloseHandle関数を使っていたが、SafeFileHandleにCloseHandleを使うと、その後にガベージコレクタがメモリを解放するときにエラーを起こすらしいと気づいたので、SafeHandle.Closeメソッドを使うように修正した。

この問題は外部コンポーネントで不規則に起こるので、なかなか原因を掴めなかったが、Stack Overflowにこれに触れたコメントがあった(How to resolve SEHException, VB .NET 2010)。MSDNなどでソースは見つけられなかったが、問題の状況によく合うし、修正してからは起こらなくなったので、当たっていたのだと思う。

2012/10/31

CrystalDiskMarkとTrim

SSDの速度を測る場合、その前の使い方(とくにライト)が影響するのはよく知られていて、Secure EraseやTrimでクリーンな状態にした後、ライトを繰り返して乱れた状態が一定以上に達すると速度低下が起こったりする。

そうした影響をなるべく防ぐための工夫は色々あり得るが、理由あって同じSSDを連続して計測する場合、その間にTrimをかけるのはどうかというアイデアを持っていた。で、最近はTrimもすっかり一般化したことだし、CrystalDiskMarkを使って試してみた(結果的には不発)。

1. 計測方法


CrystalDiskMarkを連続して実行し、その実行間にTrimをかける場合とかけない場合で差が出るかを見る。

環境
  • PC: ThinkPad X61s
  • SSD: Intel X25-M G2 80GB(OSなどで全容量の60%が埋まった状態)
  • OS: Windows 8 Pro 64bit(ドライバーはすべてOSの自動インストール)
方法
  • CrystalDiskMark(3.0.2)を4GBで空のNTFSのパーティションに対し、テスト種類All、テスト回数9、テストサイズ2000MBの設定で30回実行。
  • 実行間には1分の間隔を挟み、Trimをかける場合は前回の実行直後にこのパーティションを対象に実行(先に示した方法で)。
  • どちらの場合も最初の実行前にTrimをかける。
  • ライト量の確認のため、一連の実行の直前と直後にCrystalDiskInfo(5.1.0 RC2)でHost Writes(総書き込み量)を取得する。Host Writesはあくまでホスト側(PC本体側)から見たライト量なので、SSD内部のライト量には直結しないが、参考にはなる。なお、この間は他のライトを伴う作業はしない(OSが勝手に行うものは除く)。
SSDのX25-Mには今更感があるが、これまでの実績から見て余裕を大幅に残したまま引退となるのは確実なので、多少消耗させてもよしという事情も背景にあり。

また、こういう計測をきっちり進めていくのは結構面倒なものだが、そこはDiskMarkStreamで楽々(自画自賛)、というよりDiskMarkStreamがあったからやる気になったというべきか。

2. 計測結果


先にどれぐらいのライト量になったかを確認すると、まずTrimをかけなかった場合の実行前と実行後のCrystalDiskInfoの結果。

次にTrimをかけた場合の実行前と実行後。
(注)E9が96から95に落ちているが、96になったのはかなり以前のことなので、意味はない。

一番最初のHost Writesの生の値は76752で、この16進数を10進数に換算すると485202になる。この値は65536セクタ、すなわち65536×512÷1024^2=32(MiB)ごとに1増えていくので、容量としては以下のようになる。

485202×32=15526464(MiB)≒14.807(TiB)

同様にそれぞれの値を計算し、実行前と実行後の差から増加量を求めると、
生の値
換算後
増加量
16進数
10進数
(MiB)
(TiB)
(MiB)
(GiB)
Trimをかけなかった場合
実行前767524852021552646414.807984320961.25
実行後7DF7A5159621651078415.746
Trimをかけた場合
実行前7E15F5164471652630415.761978496955.56
実行後858D15470251750480016.694

これらの増加量はそれぞれ9×30=270回分のテストによるものなので、1回のテストの増加量は約3.54~3.56GiBとなるが、これはテストサイズが2GBということを考えるとこんなものかと思う。どちらも全増加量は1TiB近くに上っている。

ここで、X25-M G2で速度低下を起こした後にTrimで回復した例(SSDの性能低下とTrimの効き具合を大検証)を見ると、一旦容量の90%までライトで埋めている。

方法は違うが、この全増加量は全容量80GBの12倍に当たるので、変化を起こさせるに十分なライト量ではないかと思う。というか思った、が……。

結論から言うと、CrystalDiskMarkの結果は不発だった。

まずTrimをかけなかった場合、30回の実行中、ばらつきは多少あるが、有意な変化といえるものはなかった。以下は1回目、15回目、30回目のもの。

一応、次にTrimをかけた場合、同様に以下。

こちらも有意な変化はない(Trimが効果を発揮していれば変化はなくて問題ないわけだが)。

3. まとめ


1TiB近くのライトをもってして速度低下を起こせなかったのは誤算だったが、CrystalDiskMarkを連続実行しても再度Trimが必要になるような速度低下は起こらないことが確認できたので(X25-M限定でだが)、それはそれでよしとする。

しかし……、この結果を見るに、実使用でもTrimを頻繁にかける必要はない気がしてきた。1TiBなんて普通に使う限り数箇月たっても到達しない量だと思うし。

2012/10/27

CrystalDiskMarkと雫ちゃんと

Windows 8発売の26日(というか25日深夜)にCrystalDiskMarkにも3.0.2で
Shizuku Editionが登場したので、早速、当然にDiskMarkStreamで対応。

通常版との違い、サイズなどは自動で判別する。

しかし、この麗しい姿といい、青白基調の流麗なデザインといい、これを目にすると、殺伐としたベンチマークの世界(ついあれもこれもとデータを取ろうとして、環境を整えて計測しているうちに消耗戦になってきて、あまり美しい状況にはなり難い)に涼風が吹き込まれる、というより、まとめて毒気を飛ばされてしまう危険性がある……。

その意味では機械的なマクロツールであるDiskMarkStreamはそぐわない気もするが、多少矛盾をはらんでいた方が面白い、ということにしておこう。

なお、通常版のテーマのShizukuでもエッセンスは共通。

ちなみに、Windows 8ではSSDのドライブに対してコマンドプロンプトから簡単にTrimを発行できるので(Defragの/Lオプション)、DiskMarkStreamのバッチ実行機能を使えばテスト間にTrimをすることができる。


このためのバッチファイルの内容は以下のようなもの。対象のドライブはDで、結果は後から確認するためにresult.txtというファイルに出力している。
C:\Windows\System32\Defrag.exe D: /L >> C:\Work\result.txt

ただし、Windows 8が64bit版の場合、このパスではDefrag.exeがDiskMarkStreamから見えない問題がある。これは32bitのソフト(DiskMarkStreamは32bit)を64bitのWindows上で実行するときに起こり得る問題で、この場合は以下のようになる。
C:\Windows\Sysnative\Defrag.exe D: /L >> C:\Work\result.txt


どちらの場合もDefragは管理者として実行する必要があるので、DiskMarkStreamも起動時に管理者として実行する必要がある(DiskMarkStream自体は管理者として実行される必要はないが、バッチ実行を管理者として行うトリガーとし、かつバッチ実行の度にUACの承認を求められるのを避けるため)。

[追記]

Windows 8におけるTrimについて、Microsoftの担当者(Kiran Bangalore)が答えていた(Defragging SSDs a default?)。Windows 8では(Windows 7と同様に)ファイルの削除、移動の際にTrimを発行しているが、SSDの方がリアルタイムに処理できない場合を考えて、「ディスクの最適化」で定期的にTrimを発行するようになっている(これがデフォルト)とのこと。

2011/07/19

Intel SSDのE2/E3/E4

Intelの天野氏の置き土産について、自分でもよく分かってないが、とりあえず書き留めておく。

1. Endurance Monitoring #2


6/4に天野氏が最後のイベント出演をしたとき、Intel SSDの寿命予測に関してE9、あるいはHost Writesとはまた別の方法を説明していた。これが詳しく出ている記事(インテル天野氏が最後のイベント出演、Z68とSSDを語る)を見ると、これまで明らかでなかったSMARTのE2、E3、E4の意味が出てくる。

天野氏の資料によれば、
#2: Intel Timed Media Wear metric
- Allows user or system designer to evaluate the endurance wear rate for a proposed application through following SMART attributes
E2h/226 (Timed Workload Media Wear Indicator)
E3h/227 (Timed Workload Host Reads Percentage)
E4h/228 (Timed Workload Timer)

これは現在あるSSDの残り寿命がどれだけあるかを見るというより、ある負荷を与えたときにどれぐらい消耗するかを見るもののようで、
SMARTMON* tool can be used to report all SMART attributes using the following steps
- At command prompt, enter the following to list attributes:
smartctl -a /dev/hdx
- Before using a workload, enter the following to reset the E2, E3 and E4 attributes:
smartctl -t vendor,0x40 -a /dev/hdx
This issues a SMART EXECUTE OFFLINE IMMEDIATE SUBCOMMAND 0x40
- Run your workload for at least 60 minutes(できれば2時間)
- Power-cycle the system(電源を入れなおし)
- Re-enter this command to get the new values for E2, E3, and E4:
smartctl -a /dev/hdx
(注)丸括弧内は、元はIntel内部の資料だったものに天野氏が書き加えたものっぽい。

この「smartctl -a /dev/hdx」はドライブの情報を見るコマンドなので、まずこれでチェックした後で、「smartctl -t vendor,0x40 -a /dev/hdx」でE2、E3、E4をリセットし(たぶん0になる)、負荷を与えて再起動した後、再度「smartctl -a /dev/hdx」で変化を見ろ、という話(注)らしい。

(注)記事のキャプションでは少し違うことが書いてあるが、どうも分かってない感じがするので、資料の記述だけを信じる。

例として、E2が22、E3が99、E4が981のときは以下のようになる。
% Media Wearout during this run = 22(E2) /1024 = 0.021%
Work Ratio = 99(E3) % Read/Write
Workload Timer = 981(E4) mins
Lifetime using this specific workload 100% of the time 24/7 = 8.9 Years

981分間の消耗率が0.021%ということから計算して(この負荷だけをかけ続けた場合の)寿命は8.9年になるとのこと。一応計算してみると、

{100 ÷ [22/1024 ÷ 981](分当たりの消耗率(%))}(全消耗にかかる分数) ÷ {60 × 24 × 365}(年間の分数) ≒ 8.687422167(全消耗にかかる年数)

……。数字が合わないが、22/1024 ≒ 0.021484375を0.021に切り下げてから計算すると、

{100 ÷ [0.021 ÷ 981](分当たりの消耗率(%))}(全消耗にかかる分数) ÷ {60 × 24 × 365}(年間の分数) ≒ 8.887801696(全消耗にかかる年数)

合った。

いずれにせよ、E3はこの計算には入ってこない。「書き込みの割合が増えると耐久性は一気に下がる」というのは、E3が下がる=書き込みの割合が上がる負荷のときは、逆にE2は上がるという逆相関関係の意味だろうか。

2. 実験


さて、手元のX25-M G2 80GBで試してみる。コマンドプロンプトを管理者として開き、smartmontoolsで「smartctl -t vendor,0x40 -a /dev/sda」を実行(「smartctl -a /dev/sda」で表示されるものも全て入っている)。

このSMARTの部分は、226(E2)、227(E3)、228(E4)とも65535になっている。ATTRIBUTE_NAMEは、天野氏の資料ではHDDと同じだったが、この最新版(5.41-1)ではIntel SSDに対応しているようで、資料とほぼ同じ名前が短縮されたものになっている。

これはsmartmontoolsのデータベースであるdrivedb.hにあるもので、この中を見るとIntelの情報は伝わっていることが分かる。
"-v 226,raw48,Workld_Media_Wear_Indic " // Timed Workload Media Wear Indicator (percent*1024)
"-v 227,raw48,Workld_Host_Reads_Perc "  // Timed Workload Host Reads Percentage
"-v 228,raw48,Workload_Minutes " // 226,227,228 can be reset by 'smartctl -t vendor,0x40'

最後の部分では、「SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x40」に成功しているように見える。

が、この後再起動しようと何をしようと65535の数字は全く変わらなかった。このThinkPad X61s上のWindows 7 64bitのSATAのドライバをMicrosoftの標準ドライバ(6.1.7601.17514)とIntelのドライバ(10.1.0.1008)の間で変えたり、PATA(Compatibilityモード)に設定したりしても、効果なし。

念のため、CrystalDiskInfo(4.0.2a)で見た場合はこうなる。

E2、E3、E4はともにFFFFで、この16進数を10進数にすれば65535になるので、smartmontoolsと同じ(見ているデータが同じなのだから当然だが)。

あえて推測すれば、この4桁の16進数はどれも既に上限に達しているので、もう変わりようがない、ということではないかと……。これをリセットできない以上、先に進みようがない。

ということで、よく分からないまま終わる。

[追記1]

320シリーズのProduct Specificationの追補(Intel Solid-State Drive 320 Series Enterprise Server/Storage Application Product Specification Addendum)にはE2、E3、E4の説明があったので、320シリーズだけで有効なのかもしれない。

また、その説明によれば、値がFFFFなのは標準値(normalized value)ではそうなっているというだけらしい。

[追記2]

CrystalDiskInfo(4.1.0)からE2、E3、E4の名前に対応されているので補完。

日本語表記もばっちり。それぞれの詳細な意味は320シリーズの追補を読んでもらうということで。

2010/05/30

Indilinxのファームウェア

PhotoFastからIndilinxのBarefootコントローラのSSDのファームウェアが出ないと書いていたら、5月14日に1916がまとめてリリースされたので、フォローアップ。

1. アップデート作業


アップデートには他のベンダーと同じくIndilinxのプログラムを使うが、PhotoFastの場合、その前に筐体を開けてジャンパーをショートさせる必要がある。さらにG-Monster 1.8 IDE V3の場合、ジャンパーのピンが付いておらず、ジャンパーの穴の間を繋げなくてはいけないので、これが面倒だと思っていた。が、マニュアルによれば、クリップを曲げて差す程度でいいらしい。

ジャンパーの位置は、マニュアルに「1.8“44 ピンIDE」と出ている写真を見ると、J1でいいらしい。というわけで、クリップの針金を短く切って曲げたものを差してみた。
G-Monster 1.8 IDE V3: Jumper for firmware update

裏から見るとこんな感じ。
G-Monster 1.8 IDE V3: Jumper for firmware update

この状態でThinkPad X60sのウルトラベースX6に入れると(針金を短く切ったのはこのため)、デバイス名が「YATAPDONG BAREFOOT-ROM」と出る。
G-Monster 1.8 IDE V3: Device name when jumper inserted

ここでUpgrade_AP.exeを起動すると、このSSDが自動的に認識される。メモリの型番は「K9LBG08U0M」なので、K9LBGのM-Dieということになる。もっとも、プルダウンリストには32GBモデルはこれしかないので、迷いようがないが。
G-Monster 1.8 IDE V3: Selecting firmware

これを選択して「Upgrade F/W」を押すと、コマンドプロンプトが開いて実行される。
G-Monster 1.8 IDE V3: Flashing firmware

完了後のメッセージを見ると、ジャンパーを繋いだ状態が「factory mode」、離した状態が「normal mode」ということらしい。元のプログラムに戻ると、「Status」の項に「Success」と出ている。
G-Monster 1.8 IDE V3: Update completed

後は針金を抜いて終了。

2. 確認


アップデート前のCrystalDiskInfoとJSMonitorの結果はこんなもの。
G-Monster 1.8 IDE V3: CrystalDiskInfo (before firmware update)G-Monster 1.8 IDE V3: JSMonitor (before firmware update)

「Maximum Erase Count」などは結構上がってたりするが。

アップデート後はこうなる。
G-Monster 1.8 IDE V3: CrystalDiskInfo (after firmware update)G-Monster 1.8 IDE V3: JSMonitor (after firmware update)

ほとんどの値はリセットされる。これまでのデータは何だったのかという気もするが、そもそも意味は明確になってなかったようなので、気にしても仕方ないか。

2010/03/06

今年のSSD

今年のSSDの見通しについて。

1. SSD市場


CeBIT 2010の記事を見ていると、独自コントローラを持たないSSDベンダーは今年はSandForce一色になりそうな気配。


これとは別に、ついにMicronのC300が出てきたし、昨年の東芝と合わせて、話題に上がっていたベンダーがようやくSSD市場に揃ってきた。性能もリニアに伸びていく可能性があるし、多くのベンダーが競争していた、かつてのグラフィックカード市場を彷彿とさせる状況になってきたと思う。

ただ、ローカルストレージの300MB/s越えで実用上の違いがそんなに出るかという問題もあるので、現在のハイエンドのグラフィックカード市場と似てきそうな感じもする(コアなユーザー以外には関係ない世界という意味で)。

2. Mtronが消えた


Mtronの公式サイト(www.mtron.net)が繋がらない状態が続いている。最も初期のSSDベンダーだったが、消えた模様。

ちなみに、手許ではMSD6000がまだ元気に動いている。2月の寒い時期にはコールドブート一発では起動できない問題が起きていたが(古くなったPCでは時々ある現象)、3月に入って回復した。このMSD6000も今年8月で3周年になるので、いい加減交代時期に入ってきた。

3. PhotoFastってば


最近のエルミタージュ秋葉原は、どういう事情か知らないがSSDではPhotoFastを押しているようで、PhotoFastメインのSSD特集ページを作ったり、日本法人にインタビューしているが、どうなのかと。


というのも、今年の主力はSandForceらしいが(PATAではeastwho)、昨年まで主力だったIndilinxのBarefoot製品のサポートをほったらかしにしているから。Barefootのファームウェアも1916でようやく安定版に達した、というより製品自体がフェードアウトの時期を迎えているが、この1916をPhotoFastは出す気配がない。

元はといえばIndilinxが悪くて、それにSSDベンダーとユーザーが振り回されてきたというのがBarefootのファームウェアの歴史だが、他のベンダーが出している中で出さないというのでは差が付く。

SSDで重要なのはコントローラで、それをSSDにパッケージングするベンダーは基本的にどこでもいい(SSDベンダー独自の技術力はそれほど当てにしていない)。差といえば価格かサポートだが、価格は水物だから措くとして、サポートで裏切られると尾を引く(個別事例で問題があったというレベルではないし)。

SandForce製品で一番乗りしたのはいいが、これまでBarefoot製品を買ってきたユーザーは同程度のものなら他のベンダーを選ぶだろうから、今後が危ないと思う。

[追記]

PhotoFastからも5月14日付けで1916がリリースされた。

2010/01/26

X40の限界

ThinkPad X40(IDEの1.8インチHDD専用)に変換基板を介してSATAのSSDを繋げた場合、どの程度の性能まで期待できるかを確認してみた。

1. 先例


IDEとSATAの間の変換基板を介してSATAのSSDを繋げた例として、以下が見つかる。
いずれも変換基板はTEFTECの変換名人シリーズのSATA-44A(同じものが複数のルートで流通している)を使用。結線の本数は少ないので、MicroSATAコネクタを調達すれば(SSDの基板に直接、チップを傷めずにハンダ付けする自信はないので)何とかできなくもないように思う。

2. 実験


既にIDEコネクタのSSD(G-Monster 1.8 IDE V3)があるので(これもSATAのSSDをオンボードでIDEに変換しているわけだが)、性能的に交換する意味がありそうな1.8インチ以下のSSDとなると、IntelのX18-Mぐらいしか思いつかない。そこでX18-Mを繋いだらどうなるか、同性能のX25-Mを実験的に繋いで確認してみる。

変換基板は先例と同じSATA-44A。延長用のSATAケーブル(コネクタの一部を削ってある)を使用。
X40 + IDE-SATA bridge

これにX25-Mを接続。電源は別途供給する。
X40 + IDE-SATA bridge + X25-M

この状態でCrystalDiskMarkを行うと以下のようになる。
CrystalDiskMark: X40 + IDE-SATA bridge + X25-M

X25-Mをもってしてこの程度。ReadはPATA(Ultra DMA mode 5)の上限(100MB/s)を考えればそれなりだが、Writeは本来の速度が出ていない。

参考までに、G-Monster 1.8 IDE V3では以下のとおり。それぞれ得手不得手があるが、全体的にはたいして違わない。
G-Monster 1.8 IDE V3: CrystalDiskMark

試しに、Travelstar 5K500.Bを繋ぐと以下のようになる。
CrystalDiskMark: X40 + IDE-SATA bridge + 5K500.B

なぜかシーケンシャルライトの速度がSSD勢より出ているが、本来の速度よりは低い。

3. 結論


これ以上SSDを交換してもX40側の限界で性能発揮は難しいことが分かった。諦めが付いた。

2009/11/01

CrystalDiskInfoとIntel SSD

Intel SSD Toolboxと共に、ついに公開されたS.M.A.R.T.情報を受けて、CrystalDiskInfoがIntel SSDのS.M.A.R.T.に正式対応した(CrystalDiskInfo 3.1.0)。健康状態も表示されるようになっている。
CrystalDiskInfo 3.1 on X25-M G1

この健康状態はE8(Available Reserved Space)に対応したもの。Intel SSD ToolboxのUser GuideではE8は以下のようになっている。
3.4.2.8 E8 – Available Reserved Space

This attribute reports the number of reserve blocks remaining. The attribute value begins at 100 (64h), which indicates that the reserved space is 100 percent available. The threshold value for this attribute is 10 percent availability, which indicates that the drive is close to its end of life. Use the Normalized value for this attribute.

thresholdとされている10%まではまだ遠い。

E2、E3、E4が新たに表示されるようになったが、これらの意味は不明。ちなみに、03(Spin Up Time)と04(Start/Stop Count)は常に0なので、とくに意味はない。

各項目の名前は、英語表示はIntel SSD Toolboxに従ったもので、日本語表示はこれから和訳している。
CrystalDiskInfo 3.1 on X25-M G1

また、テキストコピーしたログにはそのHDD/SSDが対応しているQueue Depthが入るようになっている。CrystalDiskMark(開発中の3.0)で複数のQueue Depthを取り入れたことに対応したものか。
Queue Depth : 31

この数字は、少なくとも最近のHDDでは32なのがお約束なので、このSSDの31というのは少し不思議ではある。

2009/10/27

Intel SSD Toolbox(公開)

Intel天野氏が予告し、Windows 7発売イベントでも話に出していた(Windows 7深夜イベントはゲスト多数 古谷徹に改造バカ、神様、兄貴と総出演)Intel SSD Toolboxが公開された(Intel Solid-State Drive Toolbox with Intel SSD Optimizer Enables Users to Maximize SSD Performance over Time)。

1. S.M.A.R.T.


酷使してきたX25-Mではこんなもの。残念ながら英語だけらしい。
Intel SSD Toolbox on X25-M G1: S.M.A.R.T.

同梱のUser Guideを参照すると、
  • 05(Re-Allocated Sector Count)が1なので、4以上8未満のdefectがあることになる。
  • E8(Available Reserved Space)はパーセント表示で、まだ99パーセント残っていることになるので、余裕。
  • E9(Media Wearout Indicator)は100から1までの値をとるようなので、半分に減ったことになる。1になるともう減らないが、それでも相当量の書き込みができるようなので、実は心配しなくていいのかもしれない。
    3.4.2.9 E9 – Media Wearout Indicator

    This attribute reports the number of cycles the NAND media has experienced.

    The normalized value declines linearly from 100 to 1 as the average erase cycle count increases from 0 to the maximum rated cycles.

    Once the normalized value reaches 1, the number will not decrease, although it is likely that significant additional wear can be put on the device. Use the Normalized value for this attribute.

  • E1(Host Writes)は、65,536セクタ(=32MiB)ごとに1増えるらしいが、見るべきなのはRawの方とのこと。27.54TBということは、E9を調べたときに計算した34.83TiB以上より少ない。
一言でいえば、まだ当分は大丈夫というところか。

2. その他


Management Toolsは、G1はTrimに対応していないので、当然使えない。それはそれとして、スケジュールを組んで定期的に行うものとは思わなかった。
Intel SSD Toolbox on X25-M G1: Management Tools

Diagnostic Scanではとくに問題ないらしい。
Intel SSD Toolbox on X25-M G1: Diagnostic Scan

念のため、現在の状態をCrystalDiskMark(開発中の3.0 Alpha2)でチェック。Windows 7で既存パーティションを縮小し、4GBのパーティション(NTFS)を作成して、実行。

結果はとくに以前と変わったところはない。

2009/09/13

Intel SSD Toolbox(予定)

12日に行われた「Intel Technology Day in Akiba 2009」におけるIntel天野氏のプレゼンテーションで、IntelのSSDのS.M.A.R.T.について言及があった。AKIBA PC Hotline!に動画と資料の写真がある(「だれにも聞けないSSDの疑問」を「神様」が解説 XP/Vista用のTrimツールも準備中、廉価版の話題も)。

この中のQ6で(動画の11:38から)、SSDの寿命を判断するためのS.M.A.R.T.の項目として以下を挙げている(Q6の資料による。項目名は口頭とは少し違い、Q7の資料とも少し違うので、正式なものか不明)。
  • E1: Host Writesインジケータ(書き込み量の統計)
  • E9: Media Wearインジケータ(ウェアレベリングのレベル)
  • E8: Available Reserved Space(予備領域の残り)
また、Q7では、S.M.A.R.T.の値を見るためのツールとしてWindowsベースの「SSD Toolbox」を開発中であり、Q4に、すなわちWindows 7が出るぐらいまでにリリースしたいとのこと(SSD事業部のスケジュールは遅れがちで信用できないという問題があるらしいが)。

ということで、ようやくというか、意外に早くというか、S.M.A.R.T.の情報が公開されそうである。静かに社内で粛々と準備を進めてきていたわけで、結構なことである。

この「SSD Toolbox」のS.M.A.R.T.項目はこんな感じ(Q7の資料から。RC版らしい)。
IDDescriptionRawValueWorstThreshold
04Start/Stop Count01001000
05Re-allocated Sector Count71001000
09Power-On Hours Count51001000
0CPower Cycle Count51001000
C0Power-off Retract Count31001000
E1LBA's Written47682002000
E8Available Reserved Space0999910
E9Media Wearout Indicator099990
B8End-to-End Data Integrity Error Count010010099
(注)B8は第二世代(G2)から追加されたもの。

以前に酷使したX25-Mは現在以下のとおり。E1、E9、E8は変わってないが、いつの間にか05が1になっている。
CrystalDiskInfo (05:1)

E1の書き込み量と、E8の予備領域はまあ分かるし、しきい値からすれば余裕がありそうだが、E9の「Media Wearout Indicator」は口頭の説明でもよく分からなかった。ついでに05との関係も気になるところ。

その辺を含めて、細かい見方については然るべきときが来れば説明するとのことなので、今後に期待。

ちなみに、プレゼンテーションの最後はSSD事業部の人によるビデオで、
  • SSDを熱い砂漠上でバイク車で轢く
  • SSDを投擲する
  • SSDをジェットエンジンのドラッグカーの噴射で吹き飛ばす
この後でそれぞれSSDをノートに挿して起動してみせるもので、馬鹿馬鹿しくて笑える。

[追記1]

ひよひよさんがCrystalDiskInfoで早速、対応されている(CrystalDiskInfo 3.0.0 RC5)。
CrystalDiskInfo 3.0.0 RC5

和訳は、難しい。

[追記2]

Intel自身がまともな和訳を付けてくれるのが一番なので、以下はIntelへの駄目元のメッセージ。

「Intel日本の方、まともな和訳を付けてくださーい。Matrix Storage Consoleの「生成」なんて恥ずかしい訳にならないようにお願いしまーす!(というか、Matrix Storage Consoleの方も直した方がいいですよ)」

(参考)Intel Matrix Storage Consoleの「生成」問題

SATAの転送モードが現在どうなっているかを示す部分に、日本語では「生成」という単語が出てくるが、何かの用語かと思いきや、英語の「Generation」の誤訳である問題。
  • 150MB/s =「Generation 1」(意味的に近いのは第一世代)→「生成 1」
  • 300MB/s =「Generation 2」(同じく第二世代)→「生成 2」
「Generation」には、辞書的には「代」「世代」という意味の他に「生成」という意味もあるが、それを取り違えたものと思われる。
Intel Matrix Storage Console

この和訳を作成した人の問題もさることながら、それがそのままリリースされ、現在に至るも修正されていないことが(上は2009年9月時点の最新の8.9.0.1023)Intel社内のチェック体制に不安を抱かせるものとなっている。

なお、どうしても気になる場合は、PlugInSATA_JPN.dll中のリソースを書き換えてしまう方法がある。

[追記3]

SATAの転送モードは、Intel Rapid Storage Technology 10.1.0.1008では「1.5 Gb/秒」、「3.0 Gb/秒」といった転送速度で示されるようになった。
Intel Rapid Storage Technology