--- Begin Message ---
- To: Debian Bug Tracking System <submit@bugs.debian.org>
- Subject: bittorrent: btlaunchmany checks all files at once which hits the system hard
- From: Daniel Dickinson <cshore@fionavar.ca>
- Date: Fri, 23 May 2008 00:08:58 -0400
- Message-id: <20080523040858.28174.6526.reportbug@brennin.fionavar.dd>
Package: bittorrent
Version: 3.4.2-11
Severity: normal
Tags: patch
btlaunchmany does parallel checks of all the files in the directory at once, which if you have many files results in a huge hit to the system, with 100% CPU and max disk, plus the load average steadily climbs to a high level. The attached patch limits checking to one file at a time, which is still max CPU and large disk, but the system is not overloaded.
The important line is line #199 in the patched file:
if self.activity != 'checking existing file' and self.activity != 'disk check' and self.checking:
The rest of the patch are the deadfile removal and checking locking fixes I submitted a short while ago. I don't think they are actually needed for this bug, but I haven't tested without the full patch.
-- System Information:
Debian Release: lenny/sid
APT prefers testing
APT policy: (500, 'testing'), (500, 'stable'), (1, 'experimental'), (1, 'unstable'), (1, 'testing'), (1, 'stable')
Architecture: i386 (i686)
Kernel: Linux 2.6.24-1-686 (SMP w/1 CPU core)
Locale: LANG=en_CA.UTF-8, LC_CTYPE=en_CA.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/bash
Versions of packages bittorrent depends on:
ii lsb-base 3.2-11 Linux Standard Base 3.2 init scrip
ii python 2.5.2-1 An interactive high-level object-o
ii python-support 0.7.7 automated rebuilding support for P
Versions of packages bittorrent recommends:
ii mime-support 3.40-1.1 MIME files 'mime.types' & 'mailcap
--- bittorrent-3.4.2/btlaunchmany.py 2008-05-22 23:49:35.000000000 -0400
+++ bittorrent-3.4.2-11-pristine/btlaunchmany.py 2008-05-22 21:58:42.000000000 -0400
@@ -25,23 +25,19 @@
filecheck = Lock()
def dropdir_mainloop(d, params):
- global filecheck
deadfiles = []
global threads, status
while 1:
files = listdir(d)
# new files
for file in files:
- if file[-len(ext):] == ext:
+ if file[-len(ext):] == ext:
if file not in threads.keys() + deadfiles:
- if filecheck.acquire(0):
- threads[file] = {'kill': Event(), 'try': 1}
- print 'New torrent: %s' % file
- stdout.flush()
- status_updater = StatusUpdater(join(d, file), params, file)
- status_updater.checking = 1
- threads[file]['thread'] = Thread(target = status_updater.download, name = file)
- threads[file]['thread'].start()
+ threads[file] = {'kill': Event(), 'try': 1}
+ print 'New torrent: %s' % file
+ stdout.flush()
+ threads[file]['thread'] = Thread(target = StatusUpdater(join(d, file), params, file).download, name = file)
+ threads[file]['thread'].start()
# files with multiple tries
for file, threadinfo in threads.items():
if threadinfo.get('timeout') == 0:
@@ -58,15 +54,15 @@
# if it was checking the file, it isn't anymore.
if threadinfo.get('checking', None):
filecheck.release()
- if threadinfo.get('try') == 6:
- # Died on the sixth try? You're dead.
- deadfiles.append(file)
- print '%s died 6 times, added to dead list' % fil
- stdout.flush()
- del threads[file]
- else:
- del threadinfo['thread']
- threadinfo['timeout'] = 10
+ if threadinfo.get('try') == 6:
+ # Died on the sixth try? You're dead.
+ deadfiles.append(file)
+ print '%s died 6 times, added to dead list' % fil
+ stdout.flush()
+ del threads[file]
+ else:
+ del threadinfo['thread']
+ threadinfo['timeout'] = 10
# dealing with files that dissapear
if file not in files:
print 'Torrent file dissapeared, killing %s' % file
@@ -77,11 +73,11 @@
# if this thread was filechecking, open it up
if threadinfo.get('checking', None):
filecheck.release()
- del threads[file]
- for file in deadfiles:
- # if the file dissapears, remove it from our dead list
- if file not in files:
- deadfiles.remove(file)
+ del threads[file]
+ for file in deadfiles:
+ # if the file dissapears, remove it from our dead list
+ if file not in files:
+ deadfiles.remove(file)
sleep(1)
def display_thread(displaykiller):
@@ -166,15 +162,14 @@
if saveas == '':
saveas = default
# it asks me where I want to save it before checking the file..
-# if exists(self.file[:-len(ext)]) and (getsize(self.file[:-len(ext)]) > 0):
-# filecheck.release(0)
-# # file will get checked
-# while (not filecheck.acquire(0) and not self.myinfo['kill'].isSet()):
-# self.myinfo['status'] = 'disk wait'
-# sleep(0.1)
-# if not self.myinfo['kill'].isSet():
-# self.checking = 1
-# self.myinfo['checking'] = 1
+ if exists(self.file[:-len(ext)]) and (getsize(self.file[:-len(ext)]) > 0):
+ # file will get checked
+ while (not filecheck.acquire(0) and not self.myinfo['kill'].isSet()):
+ self.myinfo['status'] = 'disk wait'
+ sleep(0.1)
+ if not self.myinfo['kill'].isSet():
+ self.checking = 1
+ self.myinfo['checking'] = 1
self.myinfo['savefile'] = self.file[:-len(ext)]
return self.file[:-len(ext)]
@@ -196,7 +191,7 @@
self.myinfo['status'] = '%s %.0f%%' % (self.activity, fractionDone * 100)
else:
self.myinfo['status'] = self.activity
- if self.activity != 'checking existing file' and self.activity != 'disk check' and self.checking:
+ if self.activity != 'checking existing file' and self.checking:
# we finished checking our files.
filecheck.release()
self.checking = 0
--- End Message ---