簡體   English   中英

為什么Linux中的readdir()調用非線性增長

[英]Why readdir() call in linux grows non-linearly

我有一個包含1000個文件的目錄,而readdir()不到1秒,但是10000個文件大約需要24秒。

為什么? 它應該是線性的。

誰能解釋原因。 如果僅需要獲取目錄中的文件和子目錄名稱,是否有更好的解決方案?

編輯我在我的本地Linux PC上。

它可能是特定於文件系統的。 也許使用適當配置的Ext4BTRFS文件系統應該有所幫助。 一些文件系統使用散列或B樹技術使大小為N的目錄中文件訪問的復雜度為O(log N) ,而另一些仍然是線性的,例如O(N) ,並且內核可能在此之上做一些奇怪的事情。

您可能在大型目錄中使用的shell在進行glob時通常會對條目進行排序(另請參見glob(7) )。 而且您不希望它的自動完成功能在每次擊鍵時都持續數秒鍾!

我相信您永遠不會擁有巨大的目錄(例如,條目超過幾百個),因此單個目錄中的10000個文件是不合理的。 如果是這種情況,則最好以不同的方式組織文件,例如subdir01/file001.txt ... sbudir99/file999.txt

順便說一句,如果您需要通過文本鍵訪問許多小東西,則使用索引文件(如gdbm )或Sqlite “數據庫”,或真實的數據庫( PostGreSQLMongoDb ...)更適合,而且效率可能更高。 不要忘記轉儲數據(可能是以某種文本格式)以進行備份。

請注意,Linux上的readdir(3)和POSIX readdir的文檔沒有提及任何時間復雜度或任何線性行為。 缺乏提及是很重要的。 在常用的FAT文件系統上(例如在許多USB密鑰上),時間復雜度可能是二次的。

它沒有理由是線性的。 在較低級別,目錄就像文件一樣,是群集的集合。 如果它包含在一個群集中,則您只有一個實際的物理讀取操作,其余的發生在內存中。 但是,當目錄太大時,您將進行許多物理讀取。 正如Basile Starynkevitch所說,此刻它高度依賴於文件系統結構。

但是恕我直言,如果您要瀏覽目錄,它實際上取決於目錄使用的群集數量。 當您直接在一個巨大的目錄中查找文件(按名稱)時,它更多地取決於實現。 與使用本地哈希(例如BSD FFS)的文件系統相比,具有線性搜索功能的文件系統的結果將更糟。

  • 在較差的文件系統上,所有操作都應是線性的(例如FAT / FAT32為O(N) )。
  • 在像OFS這樣的良好文件系統上,查找,更新和刪除應該比線性更好O(log N) 一個完整的目錄列表仍然是線性的。
  • 無論哪種情況,它都應該比您在小型和大型情況下報告的速度快得多。

我懷疑還有其他情況。 您的結果很可能受到目錄結構以外的其他因素的影響,例如:

  • 磁盤有一個硬件問題,該問題在大型示例中觸發,但在小型示例中未觸發
  • 在較大的情況下,系統其他部分的其他磁盤活動會中斷測試
  • 磁盤硬件預取。 磁盤包含RAM高速緩存,這些高速緩存將嘗試預測下一個將要請求的扇區,並准備好它們。
  • 操作系統緩存。 操作系統還將以類似方式緩存數據。
  • 您不僅可以使用readdir數據,而且該其他操作具有較高的時間復雜度,這是主要問題。
  • 您的應用程序內存使用模式能夠適合小型目錄的L1緩存,但不適用於大型目錄。
  • 您的應用程序內存使用模式會強制在大型目錄上進行交換,但不能在小型目錄上進行交換。

readdir最多是線性的。 如果我們忽略文件系統中發生的所有事情,則從內核到用戶空間的數據量(文件名和struct dirent中的其他內容)與文件數成正比。 因此,我們從O(n)開始。

然后內核需要找出要提供的數據。 充其量線性存儲在看起來像文件的東西中。 這就是FFS和EXT2等較舊的文件系統所做的。 這為readdir提供了良好的性能(因為找到要提供給您的磁盤塊只是一個數組查找),但缺點是實際上打開這些文件( openstat或幾乎所有與該文件名一起使用的其他文件)都會變成O( n)操作,因為每次打開都必須線性掃描目錄以找到文件名。 這就是為什么在緩存這些文件系統的目錄數據方面進行大量工作的原因。 即使在那些文件系統上,您可能最終也會看到較大的目錄需要較長的時間才能讀取每個項目,因為文件信息的存儲方式隨文件大小的增加而變得昂貴。 根據文件(或目錄)的大小,內核可能需要從磁盤(或緩存)中讀取1到5個其他塊,以找出給您的塊。

如果你有一個不同的文件系統(最現代的),他們交易的線性目錄的方便性和速度的磁盤上的一個更復雜的結構,讓你的更好的性能openstat (畢竟,你為什么會readdir如果你不想對文件做任何事情?),但是結果是您(不一定,但很可能)比線性時間差,實際執行了一個readdir因為該操作找出了要讀取哪個磁盤塊您的信息可能是O(log n)。

暫無
暫無

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

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