簡體   English   中英

如何確定文件或文件夾是在 SSD 還是硬盤上?

[英]How to determine whether a file or folder is on SSD or a hard drive?

如何在 C 或 C++ 中以編程方式確定指定路徑是在閃存 (SSD) 驅動器還是磁性硬盤驅動器上? 我只對固定驅動器感興趣,對可移動驅動器不感興趣,盡管確定可移動驅動器的類型也很好。

我正在尋找一種解決方案來查詢 Windows 對指定路徑及其所在物理驅動器的看法。 沒有標桿! 另請注意,由於 SMR 硬盤驅動器,尋找 TRIM 支持不是一種有效的方法。

來自Old New Thing文章:如何判斷文件是否在 SSD 上?

這利用了我們上次學到的技巧,您可以對卷進行存儲查詢,如果卷只有一個范圍,它將報告答案。

我們不是在檢查它是否在 SSD 驅動器上,而是在檢查搜索是否免費。 對於 SSD 來說是這樣,但對於 RAM 驅動器來說也是如此。 但是RAM驅動器甚至比SSD更快,所以我認為將它們視為“超級棒的SSD”是可以的......

這是一個稍微修改的版本,不需要原始文章中的wil::unique_hfile類。

如果路徑無效,此實現不會拋出,它將報告無效路徑或網絡路徑的非 SSD。

#include <iostream>
#include <Windows.h>

HANDLE GetVolumeHandleForFile(const wchar_t* filePath)
{
    wchar_t volume_path[MAX_PATH];
    if (!GetVolumePathName(filePath, volume_path, ARRAYSIZE(volume_path)))
        return nullptr;

    wchar_t volume_name[MAX_PATH];
    if (!GetVolumeNameForVolumeMountPoint(volume_path,
        volume_name, ARRAYSIZE(volume_name)))
        return nullptr;

    auto length = wcslen(volume_name);
    if (length && volume_name[length - 1] == L'\\')
        volume_name[length - 1] = L'\0';

    return CreateFile(volume_name, 0,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
}

bool IsFileOnSsd(const wchar_t* file_path)
{
    bool is_ssd{ false };
    //HANDLE volume = GetVolumeHandleForFile(file_path);
    HANDLE volume = CreateFile(file_path, 0, 
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
    if (volume == INVALID_HANDLE_VALUE)
    {
        //invalid path! throw?
        return false;
    }

    STORAGE_PROPERTY_QUERY query{};
    query.PropertyId = StorageDeviceSeekPenaltyProperty;
    query.QueryType = PropertyStandardQuery;
    DWORD count;
    DEVICE_SEEK_PENALTY_DESCRIPTOR result{};
    if (DeviceIoControl(volume, IOCTL_STORAGE_QUERY_PROPERTY,
        &query, sizeof(query), &result, sizeof(result), &count, nullptr))
        is_ssd = !result.IncursSeekPenalty;
    CloseHandle(volume);
    return is_ssd;
}

int main()
{
    std::wcout << IsFileOnSsd(LR"(\\.\C:)") << "\n";
    std::wcout << IsFileOnSsd(LR"(\\.\D:)") << "\n";
    return 0;
}

鑒於OP在回答我的評論時所說的話,我認為這不是正確的問題

取而代之的是,這里真正重要的是查找時間 ,也許還有包含要加載映像的磁盤的延遲(請參見上面的注釋)。

當然,SSD沒有尋找時間或等待時間,因此需要並行解碼多個圖像(在單獨的線程中)以充分利用CPU。 但是OP告訴我們,這樣做會導致傳統硬盤的性能下降 ,這可能是因為磁盤頭在各處亂跳,試圖使所有解碼線程都收到數據。

那么,您能兼得兩全其美嗎? 您能否在不使磁盤不穩定的情況下充分利用CPU? 好吧,我想是的,是的。 我會做的是有一個線程一次讀取圖像到內存中,一,保持磁盤高興。

但是該線程應該只讀取“原始”圖像數據。 任何進一步的處理都應分配給一定數量的“工人”線程(確切的數量可能應限於計算機所具有的邏輯處理器的數量),以便可以並行進行。 然后,它們應該在任何類型的磁盤上全部運行。

這就是我要說的。 OP,您需要設計一些排隊/調度體系結構,但這是值得的。

如果您只想在Windows上運行它,請簽出ThreadPool ,或考慮使用std::async與C ++標准相反 ,它建立在線程池之上,並提供了不錯的C ++傳遞值語義) )。

否則,請查看C ++ Thread支持庫


編輯:對於OP來說,這顯然是相當多的工作,請參見注釋。因此,短期建議,找到某種使磁盤不穩定的方法,並測量經過的時間,以決定是並行加載圖像還是單獨處理圖像-在-A-時間。

只需並行加載一些圖像即可。 在開發過程中,在HDD和SSD上都進行測量,然后就可以確定可以用作閾值的(硬編碼)值。

注意:執行此操作時,請使用FILE_FLAG_NO_BUFFERING打開文件,否則磁盤緩存可能會騙您。

很抱歉,我在那里傳道了。 有時候我必須知道需求。

長評論:

您不必進行基准測試。 您可以在所有 N 個工作線程之間實現動態負載平衡。

獲取每個線程的每個任務的運行時間。 還要承擔每個人所做的工作量。 然后計算每個線程的歸一化性能,0.5 表示一批任務中整個工作的一半。

每批任務完成后,進行相同的計算,並根據線程的歸一化性能相應地調整線程的工作分配比例。

如果它是一個 SSD,那么所有線程都應該收斂到相等的任務分區。 如果它是 HDD,則其中一個線程應收斂到 1.0 標准化性能,而其他線程應收斂到 0。

由於這是性能感知,因此當其他應用程序(例如防病毒或其他圖像處理應用程序)同時使用 SSD 時,它不應使 SSD 的速度降低 10 倍(假設 SSD 在許多人的大量隨機訪問使用下成為 HDD應用程序),並適用於具有不同內核性能的任何非對稱 CPU 設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM