Linux
為什麼 blktrace 只寫 8 個塊?
我想了解數據庫寫入磁碟的 I/O 模式,以決定使用多少磁碟以獲得最佳性能。要分析 I/O 模式,我想使用 blktrace,我必須先了解它。這就是我在這裡嘗試的。
我有一個連接到電腦的 USB 記憶棒,它變成 /dev/sdd。現在我開始
dd if=/dev/sdd of=/dev/null
在一個單獨的視窗上我開始
blktrace -d /dev/sdd -o - | blkparse -i -
並期望看到合併 (M) 並放入隊列 (Q) 的讀取 (R) 操作。這行得通,但據我了解,塊大小始終為 8:
8,48 6 15257 2.157995037 2470 M R 816696 + 8 [dd] 8,48 6 15258 2.157996273 2470 Q R 816704 + 8 [dd] 8,48 6 15259 2.157996520 2470 M R 816704 + 8 [dd] 8,48 6 15260 2.157997794 2470 Q R 816712 + 8 [dd]
現在我停止一切並告訴系統只讀取一個字節:
dd if=/dev/sdd of=/dev/null count=1 bs=1 1+0 records in 1+0 records out 1 byte (1 B) copied, 0.00325544 s, 0.3 kB/s
這顯示在 blkparse 控制台上,如下所示:
8,48 6 1 17.220316681 2543 G N [dd] 8,48 6 2 17.220317209 2543 I N 0 (00 ..) [dd] 8,48 6 3 17.220317707 2543 D N 0 (00 ..) [dd] 8,48 6 4 17.220787473 2543 Q R 0 + 8 [dd] 8,48 6 5 17.220790545 2543 G R 0 + 8 [dd] 8,48 6 6 17.220791330 2543 P N [dd] 8,48 6 7 17.220793515 2543 Q R 8 + 8 [dd] 8,48 6 8 17.220794597 2543 M R 8 + 8 [dd] 8,48 6 9 17.220796134 2543 Q R 16 + 8 [dd] 8,48 6 10 17.220796419 2543 M R 16 + 8 [dd] 8,48 6 11 17.220797695 2543 Q R 24 + 8 [dd] 8,48 6 12 17.220797943 2543 M R 24 + 8 [dd] 8,48 6 13 17.220798862 2543 I R 0 + 32 [dd]
這裡發生了什麼?為什麼讀取一個字節會顯示為 3 個“R”請求,每個請求都有一個 Q 和一個 M 動作?為什麼它“似乎”讀取 32 或 24 個字節?文件娛樂在哪裡可以進一步教育我?
因為您正在執行緩衝 IO,並且頁面記憶體在整個頁面中工作,在 PC 上為 4k,或 8 512 字節扇區。假設 dd 將繼續讀取,核心預讀機制也會讀取更多內容。如果你想避免這種情況,那麼你需要通過傳遞 dd 的 iflag=direct 選項來使用直接 IO,但是你不能讓它讀取一個字節這樣做——直接 IO 必須對齊,並且甚至是扇區大小的倍數。
在blktrace中,+後面的數字是扇區大小的請求大小(通常為512字節,可以使用blockdev –report查看)
所以在你的跟踪中,總讀取實際上是 16kbytes。
那麼為什麼有4個’R’請求,我能想到的原因是提前閱讀。我通過使用以下命令將預讀設置為 512 字節進行了測試:
blockdev --setra 1 /dev/sdd
查看 read_ahead_kb 顯示 0
more /sys/block/sdd/queue/read_ahead_kb 0
我從執行你的 dd 命令得到的跟踪如下:
8,48 0 1 0.000000000 14412 Q R 0 + 8 [dd] 8,48 0 2 0.000002577 14412 G R 0 + 8 [dd] 8,48 0 3 0.000004467 14412 P N [dd] 8,48 0 4 0.000005627 14412 I R 0 + 8 [dd] 8,48 0 5 0.000007362 14412 U N [dd] 1 8,48 0 6 0.000008238 14412 D R 0 + 8 [dd] 8,48 0 7 0.018772074 0 C R 0 + 8 [0] CPU0 (dd_bs1_c1): Reads Queued: 1, 4KiB Writes Queued: 0, 0KiB Read Dispatches: 1, 4KiB Write Dispatches: 0, 0KiB Reads Requeued: 0 Writes Requeued: 0 Reads Completed: 1, 4KiB Writes Completed: 0, 0KiB Read Merges: 0, 0KiB Write Merges: 0, 0KiB Read depth: 1 Write depth: 0 IO unplugs: 1 Timer unplugs: 0
至於為什麼它讀取 4kbytes 而不是 1 字節,我相信這是因為 FS 塊大小為 4kBytes。因此,這是將被讀取的最小值。