[英]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...
}
我認為應該可以...
警告這是實現定義的行為,請參見此答案以獲取更好的方法。
解析由空格分隔的字符串/整數對(即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.