我正在嘗試散列一大堆檔案,并希望盡可能地使系統上的 I/O 飽和。這個用例使三件事同時成立
- 我只會讀一次檔案
- 我需要整個檔案
- 該檔案將被順序讀取
我可以合并fadvise()建議,或者如果我在同一范圍內提出多個建議,是否會覆寫另一個?
我正在嘗試三個順序呼叫,因為似乎策略不能是 OR'd like flags。
os.posix_fadvise(f, 0, 0, os.POSIX_FADV_SEQUENTIAL)
os.posix_fadvise(f, 0, 0, os.POSIX_FADV_WILLNEED)
os.posix_fadvise(f, 0, 0, os.POSIX_FADV_NOREUSE)
但在我只是建議 WILLNEED 之前。從手冊頁看來,它似乎只是設定了一個預讀緩沖區策略,而 WILLNEED 似乎是最明智的,但我需要按順序從 HDD 中獲取資料也是如此,而且我不打算第二次讀取它。
是否已定義此行為,還是僅取決于目標平臺的實施者?
uj5u.com熱心網友回復:
執行
根據我發現的這個fadvise的實作,有一個應用于通知標志的開關。您可以看到諸如預讀頁數之類的屬性file->f_ra.ra_pages確實會根據所選標志“切換”。但其他與快取相關的函式呼叫不是 ( force_page_cache_readahead)。
switch (advice) {
case POSIX_FADV_NORMAL:
file->f_ra.ra_pages = bdi->ra_pages;
spin_lock(&file->f_lock);
file->f_mode &= ~FMODE_RANDOM;
spin_unlock(&file->f_lock);
break;
case POSIX_FADV_RANDOM:
spin_lock(&file->f_lock);
file->f_mode |= FMODE_RANDOM;
spin_unlock(&file->f_lock);
break;
case POSIX_FADV_SEQUENTIAL:
file->f_ra.ra_pages = bdi->ra_pages * 2;
spin_lock(&file->f_lock);
file->f_mode &= ~FMODE_RANDOM;
spin_unlock(&file->f_lock);
break;
case POSIX_FADV_WILLNEED:
/* First and last PARTIAL page! */
start_index = offset >> PAGE_SHIFT;
end_index = endbyte >> PAGE_SHIFT;
/* Careful about overflow on the " 1" */
nrpages = end_index - start_index 1;
if (!nrpages)
nrpages = ~0UL;
/*
* Ignore return value because fadvise() shall return
* success even if filesystem can't retrieve a hint,
*/
force_page_cache_readahead(mapping, file, start_index, nrpages);
break;
case POSIX_FADV_NOREUSE:
break;
case POSIX_FADV_DONTNEED:
if (!inode_write_congested(mapping->host))
__filemap_fdatawrite_range(mapping, offset, endbyte,
WB_SYNC_NONE);
/*
* First and last FULL page! Partial pages are deliberately
* preserved on the expectation that it is better to preserve
* needed memory than to discard unneeded memory.
*/
start_index = (offset (PAGE_SIZE-1)) >> PAGE_SHIFT;
end_index = (endbyte >> PAGE_SHIFT);
/*
* The page at end_index will be inclusively discarded according
* by invalidate_mapping_pages(), so subtracting 1 from
* end_index means we will skip the last page. But if endbyte
* is page aligned or is at the end of file, we should not skip
* that page - discarding the last page is safe enough.
*/
if ((endbyte & ~PAGE_MASK) != ~PAGE_MASK &&
endbyte != inode->i_size - 1) {
/* First page is tricky as 0 - 1 = -1, but pgoff_t
* is unsigned, so the end_index >= start_index
* check below would be true and we'll discard the whole
* file cache which is not what was asked.
*/
if (end_index == 0)
break;
end_index--;
}
if (end_index >= start_index) {
unsigned long count;
/*
* It's common to FADV_DONTNEED right after
* the read or write that instantiates the
* pages, in which case there will be some
* sitting on the local LRU cache. Try to
* avoid the expensive remote drain and the
* second cache tree walk below by flushing
* them out right away.
*/
lru_add_drain();
count = invalidate_mapping_pages(mapping,
start_index, end_index);
/*
* If fewer pages were invalidated than expected then
* it is possible that some of the pages were on
* a per-cpu pagevec for a remote CPU. Drain all
* pagevecs and try again.
*/
if (count < (end_index - start_index 1)) {
lru_add_drain_all();
invalidate_mapping_pages(mapping, start_index,
end_index);
}
}
break;
default:
return -EINVAL;
}
結論
根據系統的不同,實作可能會略有不同(如果您不使用 Linux),因為 POSIX fadvise 似乎并不完全清楚圍繞不同標志組合的規則。但似乎有些屬性是結合在一起的,而另一些則不是。希望有經驗的大俠能解釋一下。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/426904.html
