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

qBittorrent hoarding tons of "VIRT" memory. "File error: out of memory" #22099

Open
nicolajkl opened this issue Jan 3, 2025 · 19 comments
Open

Comments

@nicolajkl
Copy link

nicolajkl commented Jan 3, 2025

qBittorrent & operating system versions

qBittorrent:

  • qBittorrent 5.0.3 (always latest "stable" linuxserver.io docker image)
  • Qt: 6.8.1
  • Libtorrent: 2.0.10.0
  • Boost: 1.84.0
  • OpenSSL: 3.3.2
  • zlib: 1.3.1

OS:

  • Raspberry Pi OS Light Bullseye 64 bit

Hardware:

  • Raspberry Pi 4b 8GB RAM (booting from 128GB M.2 via USB 3.0 - no SD card)
  • External 3TB 2,5" HDD for storage (with external power through powered 12V USB hub)

What is the problem?

For the past 5 years I've had this issue on my Pi 4b:
When qBittorrent has been running for at least 6 hours, problems start to occur which I suspect is due to a memory (RAM) issue.
When I look in htop I see qBit using somewhere between 100GB - 500GB of "VIRT" depending on how long it has been running for, OR when you've last performed a re-check on a torrent. "VIRT" seems to just keep climbing over time (largest I've observed was a bit over 500GB. "RES" is usually around 4-6GB and SHR a bit lower, but close to RES.

The problems:

  • Checking *large torrents causes "file error: out of memory"
  • Seeding torrents uploading very slow/not at all
  • Downloads not starting/downloading in KB/s
  • Downloads wasting data

*Might happen on smaller torrents too once the big ones start to error out with that "out of memory" warning.

Things I've tried without luck in advanced settings:

  • Set "outstanding memory while checking" from 32 to 256
  • Increase "RAM" from 1024MB to 4096MB

When qBit has been running for those 6-12 hours ish, the torrent will check for some time, and then it will error out eventually. When it has erorred out once, it will error out more or less instantly when trying again.
If I restart qBit and try to run the re-check immediately, it will succeed checking.

NOTE: the problems seem to occur only when the VIRT memory is around 400-500GB on qBittorrent.
NOTE: you can force the VIRT memory to increase by checking large torrents.

After writing all this I just realised that including the docker info would be a good idea too.
Now, I've never run the "docker info" command before, and just noticed these two lines at the bottom:

WARNING: No memory limit support WARNING: No swap limit support

Did I just find the culprit of it all here!?

Steps to reproduce

  1. Run qBittorrent on Raspberry Pi 4B with 8GB RAM (docker; linuxserver.io image)
  2. Add some large torrents (above 300GB to be completely sure)
  3. Let it seed for 6-12 hours
  4. Run a "re-check" on a torrent above 300GB and watch it "error" after some time.

Additional context

As qBit is running headless I can only access it from the webui and/or inspect the docker container.

lsblk:
image

htop with qBittorrent restarted less than a minute ago:
image

htop after checking a 308GB torrent (99,6% at the time of screenshot):
image

When the check was over, VIRT fell to 103GB.

Log(s) & preferences file(s)

qBittorrent.conf:

[Application]
FileLogger\Age=1
FileLogger\AgeType=1
FileLogger\Backup=true
FileLogger\DeleteOld=true
FileLogger\Enabled=true
FileLogger\MaxSizeBytes=66560
FileLogger\Path=/config/qBittorrent/logs
MemoryWorkingSetLimit=2048

[AutoRun]
OnTorrentAdded\Enabled=false
OnTorrentAdded\Program=
enabled=true
program=unrar x -r "%F/.r" "%F/"

[BitTorrent]
Session\AddTorrentStopped=false
Session\AlternativeGlobalDLSpeedLimit=5000
Session\AlternativeGlobalUPSpeedLimit=1000
Session\AnnounceToAllTrackers=true
Session\AnonymousModeEnabled=false
Session\AsyncIOThreadsCount=10
Session\BTProtocol=Both
Session\Categories=@variant(\0\0\0\b\0\0\0\x2\0\0\0\f\0m\0o\0v\0i\0\x65\0s\0\0\0\n\xff\xff\xff\xff\0\0\0\x4\0t\0v\0\0\0\n\xff\xff\xff\xff)
Session\CheckingMemUsageSize=256
Session\DHTEnabled=false
Session\DefaultSavePath=/obfuscated
Session\DiskIOReadMode=EnableOSCache
Session\DiskIOWriteMode=EnableOSCache
Session\Encryption=0
Session\ExcludedFileNames=
Session\GlobalDLSpeedLimit=100000
Session\GlobalUPSpeedLimit=50000
Session\LSDEnabled=false
Session\MaxActiveDownloads=1
Session\MaxActiveTorrents=101
Session\MaxActiveUploads=100
Session\MaxConnections=300
Session\MaxConnectionsPerTorrent=100
Session\MaxUploads=-1
Session\MaxUploadsPerTorrent=-1
Session\MultiConnectionsPerIp=false
Session\PeXEnabled=false
Session\PerformanceWarning=true
Session\Port=obfuscated
Session\QueueingSystemEnabled=false
Session\SSL\Port=2521
Session\ShareLimitAction=Stop
Session\TempPath=/appdata/torrents/incomplete/
Session\TempPathEnabled=false
Session\UseAlternativeGlobalSpeedLimit=false
TrackerEnabled=false

[Core]
AutoDeleteAddedTorrentFile=Never

[LegalNotice]
Accepted=true

[Meta]
MigrationVersion=8

[Network]
PortForwardingEnabled=false
Proxy\HostnameLookupEnabled=false
Proxy\Profiles\BitTorrent=true
Proxy\Profiles\Misc=true
Proxy\Profiles\RSS=true

[Preferences]
Advanced\RecheckOnCompletion=false
Advanced\trackerPort=6537
Advanced\trackerPortForwarding=false
Connection\PortRangeMin=6881
Connection\ResolvePeerCountries=true
Connection\UPnP=false
Downloads\SavePath=/appdata/torrents/complete/
Downloads\TempPath=/appdata/torrents/incomplete/
Downloads\TempPathEnabled=true
DynDNS\DomainName=changeme.dyndns.org
DynDNS\Enabled=false
DynDNS\Password=
DynDNS\Service=DynDNS
DynDNS\Username=
General\Locale=en
MailNotification\email=
MailNotification\enabled=false
MailNotification\password=
MailNotification\req_auth=true
MailNotification\req_ssl=false
MailNotification\sender=[email protected]
MailNotification\smtp_server=smtp.changeme.com
MailNotification\username=
Queueing\QueueingEnabled=false
Scheduler\days=EveryDay
Scheduler\end_time=@variant(\0\0\0\xf\x4J\xa2\0)
Scheduler\start_time=@variant(\0\0\0\xf\x1\xb7t\0)
WebUI\Address=*
WebUI\AlternativeUIEnabled=false
WebUI\AuthSubnetWhitelist=@invalid()
WebUI\AuthSubnetWhitelistEnabled=false
WebUI\BanDuration=3600
WebUI\CSRFProtection=true
WebUI\ClickjackingProtection=true
WebUI\CustomHTTPHeaders=
WebUI\CustomHTTPHeadersEnabled=false
WebUI\HTTPS\CertificatePath=
WebUI\HTTPS\Enabled=false
WebUI\HTTPS\KeyPath=
WebUI\HostHeaderValidation=true
WebUI\LocalHostAuth=true
WebUI\MaxAuthenticationFailCount=5
WebUI\Password_PBKDF2=obfuscated
WebUI\Port=8080
WebUI\ReverseProxySupportEnabled=false
WebUI\RootFolder=
WebUI\SecureCookie=true
WebUI\ServerDomains=*
WebUI\SessionTimeout=604800
WebUI\TrustedReverseProxiesList=
WebUI\UseUPnP=true
WebUI\Username=obfuscated

[RSS]
AutoDownloader\DownloadRepacks=true
AutoDownloader\SmartEpisodeFilter=s(\d+)e(\d+), (\d+)x(\d+), "(\d{4}[.\-]\d{1,2}[.\-]\d{1,2})", "(\d{1,2}[.\-]\d{1,2}[.\-]\d{4})"

Relevant part of latest log:

(N) 2025-01-03T00:29:30 - Torrent stopped. Torrent: "TORRENT_NAME"
(N) 2025-01-03T00:29:49 - Torrent resumed. Torrent: "TORRENT_NAME"
(W) 2025-01-03T00:29:49 - File error alert. Torrent: "TORRENT_NAME". File: "/torrents/complete/TORRENT_DIR/TORRENT_CONTENT.FILENAME". Reason: "TORRENT_NAME file_mmap (/torrents/complete/TORRENT_DIR/TORRENT_CONTENT.FILENAME) error: Out of memory"

Docker info:
Client: Docker Engine - Community
Version: 27.4.1
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.19.3
Path: /usr/libexec/docker/cli-plugins/docker-buildx
compose: Docker Compose (Docker Inc.)
Version: v2.32.1
Path: /usr/libexec/docker/cli-plugins/docker-compose

Server:
Containers: 8
Running: 8
Paused: 0
Stopped: 0
Images: 8
Server Version: 27.4.1
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Using metacopy: false
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: systemd
Cgroup Version: 2
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog
Swarm: inactive
Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 88bf19b2105c8b17560993bee28a01ddc2f97182
runc version: v1.2.2-0-g7cb3632
init version: de40ad0
Security Options:
seccomp
Profile: builtin
cgroupns
Kernel Version: 6.1.21-v8+
Operating System: Debian GNU/Linux 11 (bullseye)
OSType: linux
Architecture: aarch64
CPUs: 4
Total Memory: 7.628GiB
Name: OBFUSCATED
ID: OBFUSCATED
Docker Root Dir: /var/lib/docker
Debug Mode: false
Experimental: false
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false

WARNING: No memory limit support
WARNING: No swap limit support

@nicolajkl
Copy link
Author

nicolajkl commented Jan 3, 2025

I might have "solved" the issue myself by enabling cgroups in the /boot/cmdline.txt by adding:
cgroup_enable=cpuset cgroup_enable=memory cgroup_memory=1

Running a re-check on the same >300GB torrent now seems to have no impact on VIRT memory. It's stable at 96G right now.
However, my SSH terminal gets EXTREMELY slow now while performing a re-check. More than two minutes to open a txt file.

Edit:
Had the webui open and could close qbit from here. My SSH client became unresponsive.
Seems like one issue has just been replaced by another..

Edit 2:
Disabling both read and write cache in qBittorrent appears to have solved the new issue.
Will report back if other issues arise.

Edit 3:
Had to turn on cache again, as the speeds became unbearable without.
I increased the swapfile to 2GB and rebooted the machine.
Checking the same torrent again yields no problems now, and the swap is only using around 500MB at it's maximum.
I believe this has been the solution.

Now, the final test is still to see how this all runs after 12 hours. I will report back in a day or two.

@HanabishiRecca
Copy link
Contributor

This is a consequence of libtorrent 2.0 using memory-mapped files by default. See arvidn/libtorrent#6667 for details.

TL;DR: Go to Settings > Advanced and set Disk IO type to Simple pread/pwrite and restart the client.

@HanabishiRecca
Copy link
Contributor

(always latest "stable" linuxserver.io docker image)

Btw, better use the official docker image instead. That linuxserver thing already had issues in the past and qBittorrent team would not provide any support for it.

@nicolajkl
Copy link
Author

nicolajkl commented Jan 4, 2025

This is a consequence of libtorrent 2.0 using memory-mapped files by default. See arvidn/libtorrent#6667 for details.

What I wrote in the reply above yours actually seems to have fixed it. It's now way past 12 hours since I started the container, and everything appears to be working. qBit still using a lot of virtual memory, but it appears to go both up AND down now which it didn't before activating cgroups (which should allow docker to manage memory) and upping the swap file from the standard 100MB to 2048MB (maximum dphys allows me to).

TL;DR: Go to Settings > Advanced and set Disk IO type to Simple pread/pwrite and restart the client.

I don't believe this is necessary as it is working now. Highest I've seen the swap is somewhere between 500-600MB. The issue you linked is also from 2022, so perhaps the nmap issue has been fixed since? I guess there's a good reason that nmap is the standard, and simple pread/pwrite isn't?

That linuxserver thing already had issues in the past and qBittorrent team would not provide any support for it.

This issue appeared to be docker related rather than LSIO or qBit related. But hearing there's been issues in the past, doesn't sound good. I haven't faced any but this. Can you elaborate? A simple google search for LSIO qbittorrent docker issue" didn't yield much except the usual user errors regarding permissions.

@HanabishiRecca
Copy link
Contributor

qBit still using a lot of virtual memory, but it appears to go both up AND down now

With simple IO it will use close to no RAM at all.

I don't believe this is necessary as it is working now. Highest I've seen the swap is somewhere between 500-600MB.

Well, if you okay with that nonsense.

The issue you linked is also from 2022, so perhaps the nmap issue has been fixed since?

No.

I guess there's a good reason that nmap is the standard, and simple pread/pwrite isn't?

No, mmap is just bad. I implemented simple IO on qBittorrent side (#21300) to circumvent that.

@nicolajkl
Copy link
Author

nicolajkl commented Jan 4, 2025

Well, if you okay with that nonsense.

What nonsense exactly?

I will try your implementation anyway and report back if that has any effect on up/down speed and what not. 👍

Edit:
Should I restart qBit after making the change?

@HanabishiRecca
Copy link
Contributor

What nonsense exactly?

Using a lot of RAM and even swap without a reason.
In fact, increasing swap would not save you anyway. Get a larger torrent and it will fill up again.
#21300 (comment)

Should I restart qBit after making the change?

TL;DR: Go to Settings > Advanced and set Disk IO type to Simple pread/pwrite and restart the client.

requires restart is literally in the option's name.

@nicolajkl
Copy link
Author

nicolajkl commented Jan 4, 2025

Get a larger torrent and it will fill up again.

Surely 300GB should be plenty? Swap jumps around between 580-590MB.

IIRC: mmap uses RAM as cache, right? Which would be good with my limited setup when seeding? (RPi with external 5400RPM HDD). As I understand it your addition disables this and makes it read straight from disk, right?

requires restart is literally in the option's name.

Ah yes it does. I just woke up and didn't have my glasses on yet, sry bout that. :)

@HanabishiRecca
Copy link
Contributor

HanabishiRecca commented Jan 4, 2025

IIRC: mmap uses RAM as cache, right?

Not really. That's a complicated topic.

As I understand it your addition disables this and makes it read straight from disk, right?

No, you got it wrong. Regular OS file system cache will still be used.
(If you don't disable it explicitly via Disk IO read mode option below, of course.)

@HanabishiRecca
Copy link
Contributor

  • Libtorrent: 2.0.10.0

Btw, that's another reason to use the official image. There are some additional fixes for simple IO mode in upstream libtorrent repo, which could improve performance dramatically, but not yet made it into a versioned release.
Official builds pull the latest libtorrent git branch and contain all that fixes.

@nicolajkl
Copy link
Author

@HanabishiRecca I tip my fedora for you and your contribution to this project. I just tried it out, and I've never seen such speeds on my Pi. Now able to maintain speeds around 2/4 - 3/4 of my WAN speed, where before it would climb dramatically, and then average out around 10MB/s from there. I thought it was due to the limited speeds of the Pi's bus and/or my weak 2,5" Toshiba Canvio HDD.

Btw, that's another reason to use the official image. There are some additional fixes for simple IO mode in upstream libtorrent repo, which could improve performance dramatically, but not yet made it into a versioned release.
Official builds pull the latest libtorrent git branch and contain all that fixes.

I'll make the change immediately. Actually didn't know there was an official image before you mentioned it earlier. So thanks for sharing that as well.

@nicolajkl
Copy link
Author

@HanabishiRecca I've changed to the official qbit docker image now, but now I'm getting those system lags again when downloading.
I also see there's some settings missing in the advanced tab now like the I/O mode. I guess this is done to force pread/pwrite?

@glassez
Copy link
Member

glassez commented Jan 4, 2025

@HanabishiRecca I've changed to the official qbit docker image now, but now I'm getting those system lags again when downloading. I also see there's some settings missing in the advanced tab now like the I/O mode. I guess this is done to force pread/pwrite?

Maybe it uses libtorrent-1.2?
(Don't forget to mention used libtorrent version when talking about different qBittorrent builds.)

@HanabishiRecca
Copy link
Contributor

I also see there's some settings missing in the advanced tab now like the I/O mode. I guess this is done to force pread/pwrite?

Hmm, looks like release docker images are still shipped with libtorrent 1.x. 🤔
IO type selector is a libtorrent 2.x thing.

I'm getting those system lags again when downloading.

That's strange. LT 1.x should perform even better in this regard.
Try alpha tagged image.

@nicolajkl
Copy link
Author

nicolajkl commented Jan 4, 2025

Why is this considered an alpha feature only in the docker image?
I don't feel particularly safe running the alpha version. So I guess it's back to LSIO.

@HanabishiRecca
Copy link
Contributor

Why is this considered an alpha feature only in the docker image?

Libtorrent 1.x is still considered more stable experience for end users, afaik. It does not have the mmap problem at all etc.
And more performant also, according to users. arvidn/libtorrent#6667 (comment)

@nicolajkl
Copy link
Author

I need libtorrent 2.0 for 256MB piece size though. So it's either alpha or LSIO the way I see it :(

@HanabishiRecca
Copy link
Contributor

HanabishiRecca commented Jan 4, 2025

Yeah, that's unfortunate, if you don't want to build the image manually.

@Chocobo1, we probably need LT 2.0 release docker images as well.
Turns out 256 MiB piece size support is essential for some people.

@glassez
Copy link
Member

glassez commented Jan 5, 2025

@Chocobo1, we probably need LT 2.0 release docker images as well.

👍

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