Decrease dirty bytes for more reliable USB transfer

This has been requested before:

I just had a problem where I was transferring a file to a USB and dolphin showed it as pretty much instant with speeds of like 900mb/s (which is just not possible) after fixing it with the settings recommended there the file’s transfer speed gets actually properly reported (15-25MB/s).

The defaults are completely unacceptable, that feature request is from 2018, why has nothing been done about this yet? The default settings simply are not sane and this should be dealt with ASAP; with transfers to USBs being misreported like this it will confuse users, they may unplug their device only to find the files corrupted, they may try to safely remove their usb device only for it to seemingly hang messing up the experience of interacting with USB devices on their manjaro installation badly (the higher end your pc the more likely the issue is to become severe)…

In the meantime my workaround is just:

/etc/sysctl.d/98-dirty.conf

vm.dirty_background_bytes=16777216
vm.dirty_background_ratio=0
vm.dirty_bytes=50331648
vm.dirty_ratio=0
2 Likes

There is no “one size fits all” setting. Especially pay attention to @jonathon’s replies in the thread you linked.

Just because there is no “one size fits all” is not really a valid excuse, the current defaults are awful on just about any modern PC, the current settings are only sane if you have 1GB RAM or less. 2GB and you already have 200MB dirty background bytes and 400MB dirty bytes where you might be fine, but might also start experiencing issues.

The propsed settings in that thread seem like they would work on just about any modern PC, and by extension, just about any PC that happens to be running Manjaro; I mean the values are 16MB background bytes and 48MB max bytes…

While there might not be any ‘one size fits all’ if that setting is working on my PC with 32GB RAM, I have no reason to believe it wouldn’t work on a machine with 1GB RAM and anything between 1-32GB RAM, it would probably also work on a 64GB RAM machine even (although I cannot test that)

If there are issues with these settings, those issues would most likely only appear on servers (I admit that’s pure speculation though), Manjaro’s target userbase are, well, users, consumers, it’s not for server hosting therefore it stands to reason the default settings should be optimized for that.

Now certainly Jonathon is right that changing default settings should be done carefully and requires testing, but he is wrong in expecting that any user submitting a feature request or bug report would have the capability to do that testing (after all most of us only have 1 PC… and proper testing would require testing on multiple different machines); no that falls to the Manjaro team, should they decide that this is indeed a problem worth fixing.

And I don’t know, it’s been 4 years since that thread just sorta fell off and died, you tell me, do the Manjaro team care about how well Manjaro handles file transfers to and from USB’s? I suppose it’s answer enough that this issue still persists (e.g. no, they do not).

I just find it so weird that something that is this easy to fix is left broken on purpose.

That thread had a lot of good reasoning for why this should be fixed, and why it should be fixed in this way, but the manjaro team dropped the ball from their end by not addressing it for 4 years.

The short of it is, the settings are broken for absolutely anyone with more than 1GB of RAM.

Let’s do simple math, for these settings to POSSIBLY THEORETICALLY MAYBE cause a problem, the user would need to have…

Less than 240MB RAM (meaning absolutely any user with more than 256MB RAM should be completely good with the proposed settings).

I don’t see a reason to believe why this would be bad for anybody else, tell me something, how many people are running manjaro on 240MB or less RAM?

I imagine not a lot. I imagine the absolute vast 99% or higher majority of manjaro users have at least 512MB RAM (probably higher, probably 1GB)

Now I would also bet over 80% of manjaro users have over 2GB RAM, at that point the default settings start to break down. (I’m pulling these numbers out of my ass but they seem quite likely)

Now you tell me, is it better to have settings that are broken for over 80% of your users? Or to have settings that are broken for less than 1% of your users?

It’s a no brainer damn it! This is a no brainer! Now yes, it desrves testing, certainly, so test it and then when it works as it clearly should, change it please! (or at the very least provide a better reason than “we should be careful about changing defaults” for not fixing this)

There might not be a one size fits all, but the proposed settings seem to be damn close to just that (at least for end users, it might be different for servers, but manjaro, again, is not a server distribution)

2 Likes

Well I understand what you mean and on slow USB Stick. It fill up the cache and the file manager assumes it has been copied, while it is not. I understand that this could be an annoying problem on slow usb flash drives.

However… set it to:

  1. dirty → ~50MB
  2. dirty_background → ~16MB

is really low. it should be:

  1. dirty → ~256MB
  2. dirty_background → ~128MB

However… the value is only set for slow connections, while HDDs/SSDs have no problem what so ever with the default settings.

I believe even Windows has by default on the Desktop a 10% global dirty page threshold, so nothing static, but if it the threshold is arrived it switches to write-through (direct io).

Windows disables the write cache for usb thumb drives, while Linux does not by default.

A better approach:

Using a udev rule, so that it add the sync option on all usb devices:

SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ENV{UDISKS_MOUNT_OPTIONS_DEFAULTS}+="sync", ENV{UDISKS_MOUNT_OPTIONS_ALLOW}+="sync"

:warning: This udev rule is just an example. Adjuste it if needed.

Then you don’t have to worry about dirty pages, because it writes directly and synchronously. async is the default, which leads to that described behavior on slow disks.

That would be then the same behavior like on WIndows, where the write cache is disabled on usb flash drives, but it decrease the life-time of the flash drive for this usability .

4 Likes

SSDs are affected by the default settings as pointed out in that thread I linked to in the OP (Some speeds in the benchmarks got misreported beyond the actual capabilities of the device) it is just less noticable because those devices are already so fast, so if something transferring at 400MB/s but the file manager reports it at 500MB/s, usually the user wouldn’t notice it, but it’s still an issue in the background, just a minor one.

I’m pretty sure the problem would be so much bigger on HDDS that it might actually be noticable since that’s the case for SSDs, but maybe you’re right and it’s inconsequential there as well.

However, why do you say it should be 256MB and 128MB? I mean I genuinely don’t know, I don’t know where the 48 and 16 MB numbers came from for the OP (I just know they work), and I don’t know where your 256MB and 128MB numbers came from either, I do know that linus torvalds did recommend (as quoted in that other thread) 200MB and 100MB maximum

make the rule be that “the ratio numbers are ‘ratio of memory up to 1GB’”

(Which would effectively become ~100MB and ~200MB)

256 and 128 aren’t very far above those numbers so I imagine it would probably be fine, but it seems like if you go much higher than that things get wonky.

What is wrong with having the values as low as 48MB and 16MB? what is the benefit of going to 256MB and 128MB instead?

In the end I don’t really mind if it’s 256 or 48 or 64 or 128, so long as the default values work for most users I would be content, the current ones do not.

I have actually never since windows 7 was released had a problem of windows misreporting read/write speeds in filetransfers, but I do vaguely recall it happening quite a bit in the windows XP days. They must have found a solution for that. (as discussed in the archived thread they mentioned that this problem also has something to do with the I/O scheduler, maybe their actual solution to this problem happens there.

The udev rule is an interesting possible solution, but I don’t think it’s adequate because you might not always want to do that since not all USB devices or ports are created equal, the latest versions of USB can easily support SSD r/w speeds for instance (and external SSDs are a thing)

1 Like

That not a problem at all. Look: If you copy a file and async is enabled then dirty pages are filled. In fact it just show you the transfer rate to the RAM, but not the actual write speed to the disk, which works in the background constantly.

:arrow_down:

~16MB

~50MB

Well, performance, life-time and file fragmentation. That could be de/increased by a low value.

Well, maybe you have noticed that:

This policy in Windows is exactly the same as I suggested with udev rules. With sync it is written just in time, therefore “quick removal” in windows term and async is written with caching.

Yeah in that case Windows has a good simple GUI to change that while Linux has not, but udev rules. And since Linux is mainly used on servers, async is the default everywhere.

Hope all of that makes it clear and there is no need to play with the dirty pages in any way.

3 Likes

I completely support this proposal. I’ve been using values of 16MB and 32MB since that thread. This tested and retested on several machines. These values were chosen by me based on the max speed of a USB 2.0 device, and they work just fine. In my perspective these values should be set in function of the slowest storage devices used.

Have you tested this? Those settings simply set the rate at which data gets written. I’ve tested this thoroughly and there isn’t any loss in performance. What happens, in reality, is that data loss is much less probable because data is written more frequently, in smaller batches, and you don’t get mislead by reported transfer speeds. As for fragmentation, I don’t see why it should be affected. Can you please explain why?

Well, this isn’t a bad idea, but having no cache at all certainly impacts performance.

EDIT:

The logic is not to wait more than 1 second between the reported and the actual end of the transfer. If this is too restrictive, which I accept it to be (this is just my option), these values could, for example, be multiplied by 5, so no one waits more than 5 seconds on a USB 2.0 device, on average.

1 Like

No I have not, since I said “could”. That is just my expectations.

True, but on the downside it will reduce more life-time of the device, especially flash drives, same for the sync option.

That has no effect to small files, but very big files will more fragmented. As I know Linux tries to write files in one block. Let’s say you have

  1. dirty → ~50MB
  2. dirty_background → ~16MB

and a file of 1GB must be written. It reads the file stream, fill up the dirty pages and write the file in 16MB steps. Since the 16MB fill up fast, then 15sec write back schedule and the 12h expire will not be reached and it writes immediately after the 16MB is full, while it the 50MB filled up again.

So by explaining my thought here, imagine that files are written randomly on the disk to avoid fragmentation. What happens?

I know on SSDs or flash drives that has no relevance, maybe if you need to recover a file (fragmentation has bad effect here), but on HDDs it is a bad scenario.

Maybe that is more understandable now.

The thing is (and that is my opinion) you can’t set a value for dirty pages which fits them all. That is not possible. If you relay on slow usb drives then please don’t dump huge data on it, since they were not designed for this.

To fit them all, there must be a separate rule just for slow connections like usb thumb drives. Wether it is the dirty pages or just the sync option.

The root problem is here just that async (so caching) is enabled everywhere, which has an effect on slow devices. Just remember that the file manager just reports process to the ram. If the dirty pages are filled, it reports the actual write speed and when the file has been fully written to the ram, the file manager reports “successful” while the cache is still constantly written.

You will see the same behavior just on windows if performance mode is activated.

However… I believe sync should be always enabled on slow connection. Wether it is usb or a bad/slow network connection.

1 Like

And hence your earlier suggestion of using a udev rule, which addresses are more narrow scope without affecting the entire system, let alone all devices. :+1:

A “not as hacker cool” alternative is to use fstab entries with the sync and noauto option for your known USB devices.

2 Likes

If the udev rule says sync and fstab says async for a device, what will the result be? :thinking:

If fstab overrides the udev rule a combination would be a pretty decent workaround (e.g. udev rule that sets all usb devices to sync and fstab rules to override it for usb devices where you want async)

But those are hacky approaches, and the intent here is for the less savvy users to get the best results, for that it needs to be fully automated.

Simplest solution for that is changing the dirty bytes but the suggested solution by @megavolt seems like it might be ok (certainly not ideal, but ok) IF it would be easy to toggle it for specific devices, or ideally, if it would automatically detect if a usb device is fast or not and adjust accordingly (I’m not sure if this is possible short of running benchmarks on devices as they get plugged in; I mean sure, I can see the devices theoretical maximum speed reported in inxi; but it says 5Gb/s whereas the real speed is closer to 20MB/s

So wherever inxi pulls that data from seems unreliable…

I suppose an alternative maybe would be a udev rule that sets sync for certain filesystems like exFAT, FAT32 and NTFS (but some users might have NTFS drives so if the rule overrides the fstab configuration that would be bad, still at least for exFAT and FAT32 this seems like a fairly good compromise since you are very unlikely to use those filesystems (exfat and fat32 at least) for anything other than slow USB devices, I think…)

Although seeing this situation properly now thanks to megavolt’s posts (thanks for that by the way) I’m just thinking that dirty memory needs to be implemented in a smarter way (smarter so that it can actually be optimized on a per-device basis)

Setting things to sync is a solution to the falsely reported write speeds; but it comes with a performance hit doesn’t it? That’s certainly less than ideal

setting dirty memory to 256/128MB (vm.dirty_background_bytes=134217728 & vm.dirty_bytes=268435456) is not a low enough compromise; it’s low enough that at least on my ~20MB/s usb drive the misreporting isn’t too bad, it’s only a couple of seconds. On the other hand on my slowest USB device it actually is terrible (that one is sub-10MB/s speeds i think, I can’t really tell for sure because the speeds are misreported)

This situation seems quite tricky to solve, although I suppose windows does it the easiest way in which the lowest effort (from microsoft) is required. I’m beginning to understand why it’s been left unsolved for decades (then again though, while it is tricky it is not quite THAT tricky :roll_eyes: )

The udev I suggested will be ONLY applied if you put your thumb drive into the usb slot and it gets automatically mounted. That does udisks for you.

If you mount the usb drive with fstab, the default async will be used if sync is not explicitly called.

Nothing gets overwritten. There is fstab and there is udisks. Fstab is for static mounts and udisks mounts it automatically.

It is reliable. USB3 has theoretically bandwidth of 5Gb/s. Note: it is the hub. If you put 2 usb drives into the same hub it will divided. However… also the speed of the drive comes into play.

No, it is not. When using async the speed is ALWAYS not the real speed. So you have to decide yourself: Do you want that it is written just in time and unplug the thumb drive or do you want to use the cache. If the drive is always connected, then it would not make any difference, but if you need to use it just for a short time, then option sync is always preferable.

So end of story for me. You can do the hacky stuff with dirty pages, but the normal way is just using a mount option as I suggested.
I must adimit that I was wrong here when I see the results of my tiny test below. :point_down:


Additionally here a simple test from my side:

100MB tempfile on exfat with async

$ mount -t exfat | cut -d" " -f1,5,6 | sed -r "s;\(.+,(|sync).+\);\\1;g"
/dev/sdf1 exfat
$ for x in $(seq 1 5); do export TIMEFORMAT='%3lR'; echo "$(time $(cp ~/tempfile /run/media/user/Ventoy && sync))" && rm -f /run/media/user/Ventoy/tempfile && sync && sleep 1 ; done

Results:

0m6,971s
0m6,837s
0m10,505s
0m8,418s
0m10,597s

Apply udev rule:

echo 'SUBSYSTEMS=="usb", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem", ENV{UDISKS_MOUNT_OPTIONS_DEFAULTS}+="sync", ENV{UDISKS_MOUNT_OPTIONS_ALLOW}+="sync"' | sudo tee /etc/udev/rules.d/99-usbsync.rules && sudo udevadm control --reload

Unplug and plugin the flash drive.

100MB tempfile on extfat with sync

$ mount -t exfat | cut -d" " -f1,5,6 | sed -r "s;\(.+,(|sync),.+\);\\1;g"
/dev/sdf1 exfat sync
for x in $(seq 1 5); do export TIMEFORMAT='%3lR'; echo "$(time $(cp ~/tempfile /run/media/user/Ventoy && sync))" && rm -f /run/media/user/Ventoy/tempfile && sync && sleep 1 ; done

Results:

0m45,387s
0m58,523s
0m59,260s
1m4,165s
1m2,894s

100MB tempfile on vfat with async

sudo rm -f /etc/udev/rules.d/99-usbsync.rules && sudo udevadm control --reload

Unplug and plugin the flash drive.

$ mount -t vfat | grep -v sda1 | cut -d" " -f1,5,6
/dev/sdf1 vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)
$ for x in $(seq 1 5); do export TIMEFORMAT='%3lR'; echo "$(time $(cp ~/tempfile /run/media/user/USB8GB/tempfile && sync))" && rm -f /run/media/user/USB8GB/tempfile && sync && sleep 1 ; done

Results:

0m20,836s
0m17,401s
0m9,607s
0m7,731s
0m9,598s

100MB tempfile on vfat with sync

$ mount -t vfat | grep -v sda1 | cut -d" " -f1,5,6
/dev/sdf1 vfat (rw,nosuid,nodev,relatime,sync,uid=1000,gid=1000,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)
$ for x in $(seq 1 5); do export TIMEFORMAT='%3lR'; echo "$(time $(cp ~/tempfile /run/media/user/USB8GB/tempfile && sync))" && rm -f /run/media/user/USB8GB/tempfile && sync && sleep 1 ; done

Results:

20m50,983s
16m11,129s
16m15,609s
16m18,828s
16m22,699s

100MB tempfile on ext2 with async

$ mount -t ext2 | cut -d" " -f1,5,6
/dev/sdf1 ext2 (rw,nosuid,nodev,relatime,errors=remount-ro,uhelper=udisks2)
$ for x in $(seq 1 5); do export TIMEFORMAT='%3lR'; echo "$(time $(cp ~/tempfile /run/media/user/USB8GB/tempfile && sync))" && rm -f /run/media/user/USB8GB/tempfile && sync && sleep 1 ;done
0m13,881s
0m9,270s
0m8,120s
0m8,574s
0m7,631s

100MB tempfile on ext2 with sync

$ mount -t ext2 | cut -d" " -f1,5,6
/dev/sdf1 ext2 (rw,nosuid,nodev,relatime,sync,errors=remount-ro,uhelper=udisks2)
$ for x in $(seq 1 5); do export TIMEFORMAT='%3lR'; echo "$(time $(cp ~/tempfile /run/media/user/USB8GB/tempfile && sync))" && rm -f /run/media/user/USB8GB/tempfile && sync && sleep 1 ;done
4m38,701s
3m58,476s
3m55,660s
4m5,261s
4m1,574s

What is my conclusion here? There is indeed a performance impact, but it depends on the file system aswell. Maybe on vfat the options flush and sync together have a negative effect here. exfat has the best results in sync and async mode (maybe f2fs will have similar results because it is also optimized for flash drives, but it is exotic on thumb drives). All of them have similar results (more or less), therefore no doubt: async is superior even if you don’t adjust the dirty pages.

:notebook: The times also contains also the forced sync time after the copying.

I am against using the sync option after seeing these real life results. Myself I will not promote that anymore, but adjusting dirty pages is also not ideal (at least for me), So I hope the kernel devs will find a solution, but in the while I can be aware of (as I have always been) and doing a sync command after copying something to the thumb drive.

3 Likes

Life time depends on a number of factors, among which bytes written. Writing the same amount of data more frequently, in smaller batches won’t reduce the life time. I could even say it causes less heat and so it preserves life time of the device, but I would be misleading you, because, considering the writes are sequential and the total amount of data is the same, the impact on the life time is the same.

The thing is, the system knows the block being written belong to the same file, so I’m not sure your premises are correct. Since the blocks belong to the same file, the system should try to write them with low fragmentation, but I’m not sure of this, it should be tested.

Well, you can certainly set a reasonable value. Like I said, I accept my settings are too restrictive, but even Linus Trovalds agrees the defaults are not ok (I’ll search for evidence of this claim). These defaults were set in systems with very low memory. Do you think it’s ok to have a cache of 50% in a system with 32GB of ram? I have 16GB on my machines, 50% isn’t ok, there’s a high probability of data loss, and if that happens, the amount of data loss is potentially huge.

So, the Manjaro team could, for example, set this value considering the average speed of a Sata3 SSD. It would be much better than having the defaults. 256MB/128MB, as you suggested, seems fine in comparison with the defaults. As for me, I’ll keep a lower value (maybe I’ll double my settings, but that’s it).

1 Like

For me, “the average user” , this indicates to keep it default for now and only change values on the fly if really needed.
Always good to dive deeper into linux questions (and not be left confused). Nice and productive discussion.

I think you might be confused, your dirty bytes were set to the defaults right? then during your test every test done with async on would have had misreported speeds.

A good way to be certain that the file has completed transferring is hitting the safely remove button for the usb drive, if it gets removed, the file has been transferred, if it stalls, the file is still transferring and your test told you falsely that you had completed it.

There is almost definitely a performance hit, but I doubt it’s this big, that’d be completely unreasonable wouldn’t it?

(THIS IS EXACTLY MY PROBLEM! Now you have experienced it yourself!)

Try the test again but with dirty bytes set to the values I or mbb proposed earlier, your results on async will most likely be quite a lot closer to the sync speed (and you’ll be able to see the actual speed difference instead of the misreported one)

I guess you misinterpret my test. The tests with async include also the time after the cp reports that it is finished. So copy + background cache copy. It run copy xy to xy + sync background.. Even then it is faster as running it with a pure sync option. Average async speed (fg and bg copy time) is calculate at about ~10Mbyte/s and worst was at about ~5Mbyte/s while sync option goes to ~2Mbyte and below.

So to be clear. time recorded the RealTime in that case and that is no fake speed.

So I hope you understood me. Even if it write in background data, it is up to ~10x until ~100x (see vfat) faster even with default dirty page settings.

And no I am not confused about the waiting time with async (I run personally just sync in the terminal, so that it will be forced written), but I was astound how huge the gap is between async and sync on vfat for example.

From a forum search - current instance - I find a lot of topics covering the issue.

As you - by now - will have realized - there is no such thing as one-size-fits-all - as the systems are different and usb-sticks are different - the wear and tear on each individual stick is different.

So while the topic has been enlightening - the only real lesson here is

:slight_smile:

Years ago usb sticks was faster than spinning disks - then we got SSD and lot’s a memory - and the amount of data we write at a single copy operation is magnitudes bigger than we did before - yet one seems to think and expect that usb devices is still faster than disks and the copy operation should be over and done and the stick is ready to yank when the filemanager box stops spinning.

Impatience - for lack of a better phrase - causes harm to your data - and while you don’t actually notice it with your internal disk - the process is the same - usb sticks are much slower than your internal disk - the only USB which is actually fast is those built like internal disks yet removable - like a WD Passport 500G ssd - while a kingston 8G USB3 is slow as a turtle in snowy weather.

hu… yes! that is basically how it should work.

1 Like

Yeah I actually did some testing on my own and your tests do add up, with Sync on I was transferring at 1/5 the speed i had with proper async.

Moreover, I noticed a problem with the sync solution, ti doesn’t always work, when I transfer from my f2fs drive it worked, when I transfer from my xfs drive, it didn’t work (i got completely misreported speeds even with sync on)

I think I know what the real best currently available solution to this problem is though; even if it’d still be a hack.

SUBSYSTEMS=="usb", ACTION=="add", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem" RUN+="/usr/bin/sysctl -w vm.dirty_background_bytes=16777216 && /usr/bin/sysctl -w vm.dirty_bytes=33554432"
SUBSYSTEMS=="usb", ACTION=="remove", SUBSYSTEM=="block", ENV{ID_FS_USAGE}=="filesystem" RUN+="/usr/bin/sysctl -w vm.dirty_background_ratio=10 && /usr/bin/sysctl -w vm.dirty_ratio=20"

E.g. a udev rule that adjusts the dirty memory when a USB device is plugged in or out, it’s the best I can think of (although the above rule does not work, and I don’t know why, don’t really know much about how to make udev rules, maybe the action is wrong?)

But then your entire system’s cache policy is dictated by whether or not you have a USB stick plugged in? I wouldn’t pursue that route.

Why not just use “sync” (without “flush”) only for the USB drives in question? (That is, only for devices that can easily be unplugged from an external port.)

Why change the rest of the system just for the sake of USB drives?

There’s no problem with it, system doesn’t perform any worse with the dirty memory settings configured like me and mbb had it, (if anything it might actually perform slightly better) the only worry really is megavolt’s proposed theory of reduced lifetime for SSDs.

With the dirty bytes set to low whenever a USB device is plugged in you get the best of both worlds, you just gotta remember to unplug ur usb drives when you’re done using them :man_shrugging: but even if you don’t, it’s not a big deal, since the problem is theoretical after all (although this particular theory is probably correct, but you probably wouldn’t notice an appreciable decrease in ssd lifetime from just leaving a USB plugged in for a day or something anyways)

Ideally of course you should be able to set a cache policy on a per-drive basis but apparently nobody’s thought of that (not even microsoft) for like 30 good years. (although there were only maybe 20 years where it was actually needed)

However, really, I can throw your question right back at you, why not change the entire systems cache policy based on whether a usb drive is plugged in or not? You won’t notice any difference in behavior (except correctly reported transfer speeds).