[HowTo] make btrfs faster

No, that’s not a sensational headline!

In short:
Be sure to use the noatime mount option !

Make your own judgment after you try it. :footprints:

Or make your own judgment after following the link provided:

But be aware, this is a lot of text to read, and not the easiest material.

I'll try to summarize this in an easy to understand way.

Btrfs is generally said to not be the fastest of modern file systems.

There really is something to it.

But sometimes it’s just the circumstances that slow btrfs down more than necessary.

relatime

One of these circumstances has to do with the atime mount options. For compatibility reasons (and a bit overcautious) the btrfs developers decided to use relatime as the default mount option.
However, this means that every time a file or directory is read (that has not been read for more than 24 hours), the metadata of this file must be adjusted. Since btrfs works with CoW, this means that new metadata is created and written for the file.

atime

That’s not really bad. The old metadata will become invalid and deleted at some point later. But it’s just unnecessary work. (especially if none of the programs rely on atime (“mut” is such an exception))

find & grep

The problem starts with the fact that a find can access a whole range of directories. You don’t think anything bad about it, but it creates metadata. Or even a grep that looks into many files. There’s a lot of data coming together.

snapshots

But this really becomes a problem when snapshots are used (no, snapshots are really a great feature. The problem is atime!) Then the new metadata is written in the current subvolume (snapshot). But unfortunately the old metadata is still needed by the older snapshots. They describe the situation with the previous atime, as it was yesterday or the day before yesterday. The old metadata lives on until the corresponding snapshot is deleted.

lots of snapshots

Now imagine you have 100 snapshots from 25 weeks (yes, that’s an extreme example) and once a week you do a find or grep over half the disk because you’re looking for something.
Then you have the metadata of all these files visited in 25 snapshots just because of the changed atime. And you just notice that your disk is slowly becoming full, but not why.

An attempt that someone made in the linked thread shows that this is not an empty thesis. If things go wrong, then “suddenly” the disk is full. (And most of it is not the data, but unnecessary metadata)

Solution: noatime

If you use the noatime mount option, the problem will be avoided and you will avoid the following side effects

  • unexpected writing of metadata when accessing files or directories
  • duplicated metadata in many snapshots
  • increased unexpected write load with dropouts/stalls (system does not respond for a short time)
  • Unexpected disk full just because of the metadata

Mind you, this is not a problem specific to btrfs. This basically affects all file systems that work with CoW.

:footprints:

4 Likes

Far more important is that not having it shortens the life of the ssd. So it is the default option nowadays. At least on manjaro ssd on ext4 installed from calamares gui installer.
Maybe it is still not default on btrfs, i do not know.

1 Like

Indeed, on brtfs it is not active (in the default btrfs installation with Calamares). This is my fstab after the standard installation:

UUID=04BD-23C1                              /boot/efi    vfat    umask=0077 0 2
UUID=1ae306f8-6f96-40f5-a553-44b0f9df96cc   /            btrfs   subvol=/@,defaults,discard=async,ssd 0 0
UUID=1ae306f8-6f96-40f5-a553-44b0f9df96cc   /home        btrfs   subvol=/@home,defaults,discard=async,ssd 0 0
UUID=1ae306f8-6f96-40f5-a553-44b0f9df96cc   /var/cache   btrfs   subvol=/@cache,defaults,discard=async,ssd 0 0
UUID=1ae306f8-6f96-40f5-a553-44b0f9df96cc   /var/log     btrfs   subvol=/@log,defaults,discard=async,ssd 0 0
UUID=1ae306f8-6f96-40f5-a553-44b0f9df96cc   /swap        btrfs   subvol=/@swap,defaults,discard=async,ssd 0 0
/swap/swapfile                               swap        swap    defaults,noatime 0 0
tmpfs                                       /tmp         tmpfs   defaults,noatime,mode=1777 0 0

As you can see, noatime is only activated for the swapfile and tmpfs.

Perhaps this should be changed for the new installation with the Calamares default setting for btrfs.

4 Likes

You can easily test whether you are affected:

mount -t btrfs|grep -E '^[^#]'|grep -Ev 'noatime'|grep -E --color=always ',|btrfs|$'
what it does:

mount -t btrfs | search for btrfs mounts
grep -E '^[^#]' | ignore commented lines
grep -Ev 'noatime' | search lines without noatime
grep -E --color=always ',|btrfs|$' colorize the output

or

mount -t btrfs|grep -E '^[^#]'|grep -Ev 'noatime.*compress=zstd'|grep -E --color=always ',|btrfs|$'
  • You are definitely not affected if you don’t use snapshots, i.e. neither snapper nor timeshift nor anything similar. (But it is always strongly recommended to use snapshots)
  • And you certainly won’t be affected if you don’t make regular updates. (But it is always recommended for a rolling release like manjar to definitely make the updates)

The mean thing is that the system slows down at times, has dropouts, and feels sluggish at times (and with every update it will get worse), but otherwise runs stable. So there are no signs that would point to a mount option as the cause.

:footprints:

1 Like

Thank you for pointing out this weakness. Can also explain why my file tree structure got borked in mid 2023 when I had hourly snapshots on.

To cure the weakness, just replace any relatime in btrfs lines with noatime in fstab?

1 Like

“Borked” could mean a billion things. Hourly snapshots do not cause this on their own.

But you either add the option noatime, or replace it if one of the others is there. (e.g.: relatime, atime, noatime, strictatime, lazytime)

1 Like

Some other things that may be worth mentioning,

The beauty of these next two things, is you can make them filesystem wide, or per file or directory.

Compression. At the default zstd compression level of 3 I was able to pin a core writing to an older HDD, yes an old 6 TB HDD. So I took it off on all volumes. Especially now, with With 2TB SSDs becoming standard (and much faster), I would only put compression on very specific things.

Also, disabling CoW for certain directories can be handy too. For example, I have no-CoW on /var/lib/libvirt/images, for QEMU virtual disks. But transaction heavy apps, like databases also benefit here. (But these will not get included in snapshots, as well as disable checksum validation.) But it can be well worth it for many use cases, and you just handle these situations differently for snapshotting and backing up.)

Putting these no-CoW directory/volumes on a different filesystem is often preferable, but it’s nice to have a convenient in the middle solution.

And the quick way to instantly start using parts of it, is by setting attributes on specific parts of your filesystem. With chattr +c for compression, and chattr +C for no-CoW. (But this require a btrfs filesystem defrag after. Without the defrag, only the new data written will adhere to it. But the defrag can run over an entire btrfs filesystem, or even just a single file/directory.)

1 Like

What about the lazytime mount option?
From what I have read, though I may not have read or understood enough, it would seem advantageous to use than noatime, though do the benefits depend upon the filesystem and perhaps its application?

I think I read that lazytime is a default option unless an overriding option is specified.

If you follow the link in the first post, everything is described in detail.

You can see it yourself using the commands in the first post.

:footprints: