--use-fs-snapshot slows down backup by >10x

When I tried Restic on Windows before, I found it unusably slow. See my thread: Backup on Windows: slow and crashed

I tried again, this time with a backup of just data, not the whole system. Still that’s 2.5 TB. And, as last time, it was very slow. Two hours in, it was projected to take 35 hours more. The backup medium is a Samsung NVME SSD in a Thunderbolt enclosure.

That was until I removed --use-fs-snapshot. Now, it’s projected to take 3 hours. That is reasonable!

Is that expected?

My system:

> restic version
restic 0.18.1 compiled with go1.25.1 on windows/amd64
> systeminfo | findstr /B /C:"OS Name" /B /C:"OS Version"
OS Name:                       Microsoft Windows 11 Pro
OS Version:                    10.0.26100 N/A Build 26100

Now I cannot replicate the fast execution anymore. :frowning:

Even without --use-fs-snapshot, the backup is projected to take one to two days. As last time, this means I cannot use Restic. This is a portable computer. It won’t stay connected to the USB disk for that long.

It’s so weird, because at one time it did show it can do it in three hours.

I think the unfortunate reality is that this was simply an erroneous estimate, and it would never have been able to complete the backup in 3 hours.
Pulling numbers for the Samsung 990 Pro SSD, reviewers quote around 1400MB/s for sustained write loads (a far cry from the 6900MB/s quoted on the datasheet). That would be ~4hrs to transfer 2.5TB. So even just copying the files, 3hrs would be a stretch.
It’s possible the estimate was so low because you already uploaded the first chunks of data during your “–use-fs-snapshot” run. So perhaps restic was going quickly as it was only encountering data it already had written to the repository. Once it started encountering new data, the estimate changed to be more accurate.

I remember that thread, just skimmed through it to refresh my memory.

I’m probably going to repeat myself here, but 2.5TB is a lot of data.
Thunderbolt saturates in the region of 1000s of MB/s (depending on the version), and the same for NVMe SSDs. However, as we discussed in the last thread, restic isn’t going to get anywhere near that, given it is “chunking” (i.e. splitting and hashing) each changed/new file in the dataset, and during the first backup, all the files are “new”.

I mentioned in the last thread I see about ~230MB/s, using local SSD storage, on a relatively modern (Ryzen 5 5600X) system, and that the speed of restic processing (CPU) is the limiting factor.
You were getting nearer 40MB/s before, and based on the 2.5TB/37hr estimate it looks like you’re now getting around the ~150MB/s mark, which is almost 4x faster. Yay for local storage!

I think I can only really re-iterate what I said last time; the first backup will be slow. Subsequent backups will be several orders of magnitude faster (depending on how much your dataset does or doesn’t change).
If you’re still interested in testing restic, I think unfortunately you’re going to have to get through the first backup before you’ll be able to have any real idea of what the day-to-day performance will be like.


Something that might make the first backup easier, but requires some manual effort, would be to back up the dataset in pieces during the initial backup, instead of all in one go.
Let’s take an example dataset of /mnt/data, where under /mnt/data there are a bunch of subfolders, a through z.

  • To avoid having to back up all of /mnt/data in one go, we can back up the subfolders one, or many, at a time, so that we limit the total amount of data being ingested in each backup run.
  • Every new snapshot we take, we add more subfolders, such that by the end of the process, we’re specifying all of the folders under /mnt/data, i.e. the complete dataset.
  • In between each backup, we take a note of the snapshot ID that was previously created, and we tell restic to use it as the “parent” snapshot for each subsequent snapshot. Restic won’t upload the data twice anyway, but this lets the path-based file change detection work effectively.

Our example first backup would be:

restic backup /mnt/data/a /mnt/data/b

And our example second backup would be:

restic backup --parent 12a345b6 /mnt/data/a /mnt/data/b /mnt/data/c /mnt/data/d

Where 12a345b6 is the ID of the previous snapshot we took (the one of /mnt/data/a /mnt/data/b). This can be found by running restic snapshots or read from the previous backup run output.

Repeat this process until all subfolders in /mnt/data have been backed up, then run one final backup:

restic backup --parent a123456b /mnt/data

Where a123456b is again the ID of the previous snapshot.

  • After this, you would restic forget all the “staging” snapshots (those where we specified the subfolders as the backup target).
  • From here on, backup the entire /mnt/data directory, and don’t bother specifying any subdirectories anymore.
  • Your next scheduled backup after this should be a good indication of the time this backup will take when run regularly.

The point of this process is to limit the amount of new data ingested, and therefore how long each individual backup takes.
Restic has file change detection functionality, which means the previous data doesn’t have to be fully processed: Backing up — restic 0.18.1 documentation
By splitting the backup into segments, we can leverage that functionality to keep the time taken to complete each backup segment down, while simultaneously increasing how much of the total dataset we have backed up.

Based on you liking the 3hr mark, backing up maybe 250Gb chunks of your total dataset would get close to that (should take ~3:45h), this would require 10 backup runs to do all 2.5TB.
If you can keep the system on for longer, ~500GB should be in the region of a 7.5h runtime, and would require 5 individual backup runs.

Note that all the numbers above are rough estimates based off the 2.5TB/37hr number, which is itself a rough estimate. You may find the system performance varies significantly from this.

2 Likes

Here’s a contrived example showing the process in action:

❯ restic -r repo1 backup data/a
repository fe33d4fa opened (version 2, compression level auto)
created new cache in /home/user/.cache/restic
no parent snapshot found, will read all files
[0:00]          0 index files loaded

Files:           1 new,     0 changed,     0 unmodified
Dirs:            2 new,     0 changed,     0 unmodified
Added to the repository: 5.000 GiB (5.001 GiB stored)

processed 1 files, 5.000 GiB in 0:42
snapshot d75cdcbb saved
❯ restic -r repo1 backup --parent=d75cdcbb data/a data/b
repository fe33d4fa opened (version 2, compression level auto)
using parent snapshot d75cdcbb
[0:00] 100.00%  1 / 1 index files loaded

Files:           1 new,     0 changed,     1 unmodified
Dirs:            1 new,     1 changed,     1 unmodified
Added to the repository: 5.000 GiB (5.001 GiB stored)

processed 2 files, 10.000 GiB in 0:39
snapshot f4b2128b saved
❯ restic -r repo1 backup --parent=f4b2128b data
repository fe33d4fa opened (version 2, compression level auto)
using parent snapshot f4b2128b
[0:00] 100.00%  2 / 2 index files loaded

Files:           0 new,     0 changed,     2 unmodified
Dirs:            0 new,     0 changed,     3 unmodified
Added to the repository: 0 B   (0 B   stored)

processed 2 files, 10.000 GiB in 0:00
snapshot f9eb81f1 saved

versus backing up the same data all in one go:

❯ restic -r repo1 backup data
repository 798d2f11 opened (version 2, compression level auto)
created new cache in /home/user/.cache/restic
no parent snapshot found, will read all files
[0:00]          0 index files loaded

Files:           2 new,     0 changed,     0 unmodified
Dirs:            3 new,     0 changed,     0 unmodified
Added to the repository: 10.000 GiB (10.001 GiB stored)

processed 2 files, 10.000 GiB in 1:20
snapshot 2db9cdb9 saved

total time to backup the dataset is approximately the same (80s) using both methods. Of note; the final snapshot in the segmented approach is effectively instant, because there is no new or changed data to process.

I see, and I could indeed replicate that scenario.

My machine is old, although when I look at CPU utilization during the backup, the Restic process hovers between 10% and 20%. The CPU is a Core i7-8650U, according to dxdiag.exe.

No need to test. I have several Restic setups, but they’re all on Linux machines, mostly servers. I know that performance is great. In fact, I back up the exact same data, synced by Syncthing, on a Hetzner server to one of their storage boxes. Restic is so quick that I increased the backup frequency to every two hours. If I wanted, I could run it every few minutes.

But I also like to have an offline backup, which so far on Windows I’m doing with Macrium Reflect. Macrium provides a good tool for incrementally imaging the system partition. However, for plain data, I never found Reflect that great. In particular, it often has an excuse to do another full backup, even though it is configured to do incrementals forever.

Thank you very much for the detailed explanation on how to do that! I’ll be traveling a bit in the upcoming days, might give it a shot afterwards.

I wonder if alternatively I could just sync for a few hours every day, then kill the process and continue the next day. From you comment quoted at the top, I get that chunks already written don’t need to be written again.

1 Like

Ok, in which case it surely isn’t cpu that’s the limiting factor behind your speed for this backup :slight_smile: unless you were seeing something like a single core pegged at 100% while the others were all idling I suppose :smiley:

You’re most welcome. If you do give it a try, please do report back with your results.

You absolutely can, data that has been written to the repository won’t need to be written again (FAQ: will restic resume an interrupted backup). The disadvantage of this approach though is restic has to scan the entire dataset again when the backup job is restarted, which, at 2.5TB, probably takes a measurable amount of time.

Backing up the dataset in pieces avoids this, as restic will match the metadata of the files against those stored in the previous snapshot, and avoid re-scanning any files that have not been modified. Which is much faster than re-scanning everything. The trade-off is that this approach involves more manual labour than just hitting ctrl+c to interrupt a running backup, so it’s up to you whether it is worth the additional hassle.

Thanks again for the detailed explanation!

Last night, I let Macrium Reflect do a full image to Samsung T7 Shield, which is a USB 3.2 drive:

New File: 2.89 TB       653EEC9E4EC1501C-00-00.mrimg

--------------------------------------------------------------------------------
Image Completed Successfully in 09:24:04
I/O Performance:        Read 13.0 Gb/s - Write 1.2 Gb/s

Of course, this is a block level backup, so a different beast. I note this more for my own reference.

(My goal is to eventually split the partition into a system and a data partition, where the system partition is backed up with Reflect and the data partition is backed up with Restic.)

@feklee, did you complete your backup, are you able to enjoy restic on Windows?

Not yet, because the USB 3 and Thunderbolt functionality of the ports of my machine stopped working. That’s due to bad contacts. USB Type-C is flimsy. I hope to get that fixed once I find time. In the meantime, I’m relying on online backups, which run on my file server. Also with Restic, of course.

As far as I can tell, Restic for backing up the data partition plus Macrium Reflect for backing up the system partition is a good combination.

Originally, I used exFAT on the backup medium. After switching to NTFS, performance went up considerably. See my October 8 post in the thread Windows: Recommended allocation size for exFat?.