У меня есть программа pygtk, предназначенная для работы как в Windows, так и в Ubuntu. Это Python 2.7 и gtk2 со статическими привязками (т.е. без самоанализа gobject). Проблема, с которой я столкнулся, существует в Ubuntu, но не в Windows.
Предполагается, что моя программа может обрабатывать большое количество файлов (здесь я тестирую около 200), но фактическая обработка каждого файла невелика. Я ставлю обработку в очередь для каждого файла и представляю прогресс пользователю.
Проблема в том, что после выбора файлов с помощью gtk.FileChooserDialog (control-A - ваш друг) программа зависает, и события gtk не обрабатываются в течение достаточно долгого времени - даже если моя функция обратного вызова вернулась. За это время загрузка процессора всеми ядрами зависает примерно на 80%, iotop
показывает, что мой процесс записывает на диск со скоростью около 20 МБ в секунду, а другие приложения периодически перестают отвечать на запросы - Chrome, Xorg, compiz, banshee и gedit имеют высокую загрузку ЦП (при низкой загрузке до выбора файлов).
Вот пример кода. Чтобы воспроизвести, нажмите кнопку, выберите где-то около 200 файлов (примерно десять экранов, удерживая нажатой клавишу shift и down) и нажмите OK. Не имеет значения, какие файлы - с ними ничего не делается.
import gtk,gobject,time
def print_how_long_it_was_frozen():
print time.time() - start_time
def button_clicked(button):
dialog = gtk.FileChooserDialog(
'Select files to add', w, gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
dialog.set_select_multiple(True)
dialog.set_default_response(gtk.RESPONSE_OK)
response = dialog.run()
files = dialog.get_filenames()
dialog.destroy()
for i, f in enumerate(files):
print i
global start_time
start_time = time.time()
gobject.idle_add(print_how_long_it_was_frozen)
w = gtk.Window()
b = gtk.Button('Select files')
w.add(b)
b.connect('clicked', button_clicked)
w.show_all()
gtk.main()
Это приводит к ~ 60-секундному зависанию после обратного вызова, завершенного, в течение которого ничего не должно происходить, кроме обработки уничтожения диалога (что происходит на полпути через зависание).
Это на Ubuntu 11.10. В Windows меньше секунды зависания.
У меня есть подозрения, что это связано с тем, что в Gnome или Unity есть функция 'недавние файлы', или с другой активностью отслеживания. процесс zeitgeist-daemon
также сильно загружает процессор во время зависания, хотя его устранение не решает проблему. Также не отключено ведение журнала с помощью Zeitgeist Activity Log Manager. Даже если Zeitgeist можно отключить, я не могу ожидать, что мои пользователи отключат его.
Кто-нибудь знает, как отключить отчеты о последних файлах в приложении gtk, или знает что-нибудь еще, что может быть причиной этого?
Чрезвычайно большое количество файлов нужно будет добавить для обработки через диалог «выбор папки», но для меньшего числа файлов время зависания составляет около половины секунды на файл, что не совсем приемлемо для приложения, реагирующего на другие проблемы.
(тестирование проводилось на 32-битных Windows 7 и 64, но на Ubuntu 11.10. Python 2.7 и pygtk 2.24 на обоих)