Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Measure free space fragmentation #50

Open
Massimo-B opened this issue Jan 23, 2025 · 4 comments
Open

Measure free space fragmentation #50

Massimo-B opened this issue Jan 23, 2025 · 4 comments

Comments

@Massimo-B
Copy link

Hi,

from Zygo/bees#298 (comment) I learned that btrfs-balance-least-used can help to reduce free space fragmentation reducing the btrfs performance on HDDs a lot.
Is there any tool to measure free space fragmentation?

@knorrie
Copy link
Owner

knorrie commented Jan 23, 2025

Hey! Yes, there is an example script that I wrote for this: https://github.com/knorrie/python-btrfs/blob/master/examples/show_free_space_fragmentation.py

Ah, there's also an old branch in the repo, which still contains an adjusted version of this, which actually creates a picture of the block_group using btrfs-heatmap, and then calls btrfs balance to clean it up, one at a time: https://github.com/knorrie/python-btrfs/blob/meuk/balance_fragmented/examples/balance_fragmented.py <- This thing should still 'just' work, but if you want to use it, I'd recommend copying it out of that old branch and running it with the current version of the python-btrfs lib.

Here's an example of the output collection of pictures, back in the time when I was running this: https://syrinx.knorrie.org/~knorrie/btrfs/fragmented/ The second field in the filename (e.g. 000291) is the bad free space fragmentation score. Browsing those should give an idea about what score probably relates to what layout inside.

Have fun!

@knorrie
Copy link
Owner

knorrie commented Jan 23, 2025

Also, notice that free space fragmentation can have very different effects on hdd performance than actual file fragmentation.

The result of using btrfs balance is that data storage gets compacted by tetrissing data extents into already available free space. This is very different than actually defragmenting individual files, so that the chance increases that the content of a single file is stored closer to each other.

IOW, btrfs balance does not defragment / optimize file content, it just shovels around existing small or large file extents to some other random place on disk.

@Massimo-B
Copy link
Author

As discussed in the other thread, I confuse the terms "data chunks", "block groups", "blocks" and "extents". These concepts should be centrally described in the man-pages or some wiki.
Zygo/bees#298 (comment) already tried explaining:

A dev_extent is a contiguous region of physical space on one device. A chunk is one or more dev_extents organized in a RAID profile. A block group is a chunk with a free space counter. Block groups and chunks are very similar, and the terms are used interchangeably in cases where the presence or absence of the free space counter is not important.

So for me, when the man-page talks about block groups or chunks, it's almost the same. Still makes me ask, what is a block then, same like a dev-extent?
A block group on a single device does still reference multiple dev_extents so is not physically contiguous?

An extent is a contiguous region of logical space in a block group. A file is a list of references to extents, indexed by offset from the beginning of the file. Extents are always contiguous--one fragment is one extent by definition. Extents are created when writing to a file, and can be smaller than the written region if the written region exceeds the maximum size for an extent, or if the largest free space available in any block group is smaller than the written region.

So dev_extents are different from extents, dev_extents are contiguous physically on device, extents are contiguous logically in block groups?

And:

Balance moves extents from one block group to others

This is what you metaphorically call tetrissing. It compacts block groups, filling the existing and dropping the empty block groups. Talking about free space, there is the free area in already reserved block groups and the real free space that is not occupied for any data or metadata blockgroup.
That means balancing reduces the reserved free space fragmentation over block groups. But as block groups are not contiguous and this does not change the fragmentation of the unreserved free space, does it help at all to improve bad HDD performance?

About your btrfs-balance-least-used: From what I learned in the other thread, btrfs-balance-least-used -u 80 actually has the same goal like btrfs balance start -dusage=80 but is faster and more efficient because of the order of processing least used chunks first?

@Zygo
Copy link

Zygo commented Jan 25, 2025

So for me, when the man-page talks about block groups or chunks, it's almost the same. Still makes me ask, what is a block then, same like a dev-extent?

Block groups map logical addresses to chunks, chunks map those to devices and dev_extents. Block groups contain extents, extents contain blocks.

A block group on a single device does still reference multiple dev_extents so is not physically contiguous?

This depends on the block group. dev_extents are always physically contiguous and exist only on one device. Chunks point to (device, dev_extent) pairs, and combine them with a raid profile to specify the translation from logical to physical addresses. The raid profile defines how many dev_extents there are and how the chunk uses them. e.g.

Single profile: chunk contains one dev_extent from one device.
Dup profile: chunk contains one dev_extent from one device, but splits it into two parts, with a duplicate copy of the first part mirrored in the second.
Raid1 profile: chunk contains two dev_extents, on two different devices. Data is mirrored between the dev_extents.
Raid1c3, raid1c4: same as raid1, but with 3 or 4 dev_extents and devices respectively.
Raid0 profile: chunk contains N dev_extents, on N devices. Data is striped between the dev_extents.
Raid10 profile: chunk contains 2N dev_extents on 2N devices. dev_extents are divided into two groups of N devices, with mirroring between the 2 groups, and striping within the N drives.
Raid5 profile: chunk contains N dev_extents on N devices. dev_extents are striped, with N-1 devices carrying data and one containing parity in each stripe.

So dev_extents are different from extents, dev_extents are contiguous physically on device, extents are contiguous logically in block groups?

Yes.

Balance moves extents from one block group to others

This is what you metaphorically call tetrissing. It compacts block groups, filling the existing and dropping the empty block groups. Talking about free space, there is the free area in already reserved block groups and the real free space that is not occupied for any data or metadata blockgroup. That means balancing reduces the reserved free space fragmentation over block groups. But as block groups are not contiguous and this does not change the fragmentation of the unreserved free space, does it help at all to improve bad HDD performance?

dev_extents are typically large, most are only one size (1G) while extents are smaller and variable size (4K to 128M). dev_extent fragmentation is possible, especially when frequently resizing a striped profile. It is typically many orders of magnitude less than extent fragmentation because the free spaces between extents are much smaller and have many different sizes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants