簡體   English   中英

解析mmap()版本的文件

[英]parsing a mmap()-ed file

通過mmap-ed文件解析的最佳(最快)方法是什么? 它包含成對的數據(字符串int),但是我不能認為它們之間有一定數量的空格/制表符/換行符。

假設您已經映射了整個文件(而不是大塊的文件,因為那樣會使生活變得非常復雜),我將執行以下操作...

// Effectively this wraps the mmaped block
std::istringstream str;
str.rdbuf()->pubsetbuf(<pointer to start of mmaped block>, <size of mmaped block>);

std::string sv;
std::string iv;

while(str >> sv >> iv)
{
  // do stuff...
}

我認為應該可以...

警告這是實現定義的行為,請參見此答案以獲取更好的方法。

如果最好/最快的意思是最容易編寫代碼,那么這是不推薦使用的std::istrstream適合的罕見情況之一; 調用istrstream::istrstream(char const*, std::streamsize)構造函數重載,然后像從其他任何std::istream一樣從流中提取數據。 (這不會像std::istringstream那樣復制底層內存。)

如果以最佳/最快的速度表示最佳/最快的運行時性能,我認為您將無法擊敗boost 精神 qi或手寫解析器,盡管我認為前者更容易編寫和維護(如果您以前從未使用過boost.spirit,則可以忽略圖書館學習曲線)。

解析由空格分隔的字符串/整數對(即foo 50 bar 20 baz 123)應該快如閃電。 到目前為止,更重要的因素是
a)頁面實際上在RAM中,僅mmap不能保證
b)緩存行在L1緩存中

默認情況下,雖然mmap在順序訪問中確實已預先讀取,但磁盤訪問的時間為數十毫秒 ,而對4k頁內存的解析(理想情況下)為數十微秒。
因此,您不能指望預取器能夠跟上步伐,特別是因為它只會在看起來您需要更多時才進行預取(即使假設查找時間為零,由於機械磁盤上​​的旋轉延遲,它實際上也保證了前期成本)。
因此,除非您的總數據只有十幾個千字節(在這種情況下,無論如何,如何盡可能快地處理它都是毫無意義的),在開始掃描之前先瘋狂(MADV_WILLNEED)是有意義的,因此系統不會等着看您的訪問模式觸發它的啟發式方法,而是順序地讀取它可以不間斷地讀取的內容。 一旦超過訪問時間,磁盤帶寬(順序)就很大。 您可能仍然會追上來,但要晚得多。 如果您的數據集足夠大,因此可能不適合放入RAM,則對時不時看到的數據調用MADV_DONTNEED是一個好主意。

對於頁面錯誤,也適用於高速緩存未命中。 緩存的負載為1-2個周期,內存的負載為200-500個周期。
CPU具有針對順序訪問模式的自動預取功能,但是受到限制。
首先,預取永遠不會跨越頁面邊界。 那是因為如果是這種情況,那么自動預取將有規律地觸發頁面錯誤,這將是非常不愉快的。
其次,僅在連續兩次未命中之后才進行預取,這是為了確保僅在可能有意義的情況下才啟動預取。 為每個隨機讀取預取相鄰的緩存行將是愚蠢的,因為這會不必要地浪費寶貴的緩存行。
第三,預取需要時間,一旦CPU中的啟發式觸發器觸發,您就已經在爭奪數據,因此,早於晚。
幸運的是, 您知道將需要什么數據,並且知道很長時間了。 因此,您可以給出預取提示,這將為CPU提供寶貴的開始時間(例如,預取半個千字節)。

就目前而言,您的問題太含糊而無法回答。

不過,如果你需要做的是讓一些數據出來的文件,你不想做的是使用將在修改內存的方法mmap編輯區域。

編輯現在,您已經編輯了問題,這更加清楚了。 作為起點,我將使用單個char指針來遍歷整個mmap ed文件。 提取字符串非常簡單(確切的方法取決於您需要對結果執行什么操作),並且可以使用atoi等人提取整數。

您可以通過std::string訪問它,並使用std::istringstream以便順序讀取它。 或者使用一些更方便的庫,例如,在Qt中,您可以在從映射的內存構造的QByteArray上使用QTextStream

暫無
暫無

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

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