Детали приложения: приложение pyQt, Qt 4.4 и python 2.5
Проблема: с течением времени (при длительном использовании приложения без закрытия) приложение иногда работает медленно. Я попробовал большую часть приложения для профилирования, но не нашел ничего существенного, чтобы указать на какую-либо проблему.
Мое приложение создает несколько таблиц на разных вкладках, используя QTabWidget. Поэтому, чтобы ускорить переключение вкладок, я создаю таблицу только один раз и сохраняю QTableWidgetItem в памяти.
Число QTableWidgetItem колеблется в пределах ~ 5000 - 10000. Существует больше таких объектов (# ~ 600 - 800), которые создаются и должны храниться в памяти, пока что-либо не изменится.
Я думал, что GC может иногда замедлять мое приложение. Потому что пороги GC по умолчанию составляют 700,10,10. В моем случае 700 кажется очень меньше. И эти QTableWidgetItem остаются в памяти, пока не будут изменены какие-либо данные. Так может ли GC часто включаться в фазу 1, фазу 2 и фазу 3?
Как только данные изменены, я просто отменяю ссылку, выполняя mytable.setRowCount (0). В этом случае мне не нужен GC для восстановления памяти. Я прав ?
Могу ли я сказать GC не отслеживать некоторые из этих объектов?
Пожалуйста, предложите, если мое понимание неверно?
Также, пожалуйста, дайте мне знать, если вопрос неясен.
def fetchData (self, win=None):
"""Fetches data from the data sources.
"""
start = time.clock()
changed = self.adjustDateRange()
if not changed and self.chartEdition == self.fetchEdition: return
badIngredients = []
ingredientList = self.getIngredientList()
parentWin = win
if parentWin is None:
parentWin = qApp.activeWindow()
B = 0
N = len(ingredientList)
if N == 0: return
progress = QProgressDialog(parentWin)
progress.setWindowModality(Qt.WindowModal)
progress.setWindowTitle ("FetchData Progress")
progress.setRange (0, N)
#progress.forceShow()
self.lock()
try:
for i in xrange(len(ingredientList)):
progress.setValue(i)
if B > 0:
progress.setLabelText("Fetching time series %s of %s\n"\
"Number of missing series: %s" % \
(i+1,N,B))
else:
progress.setLabelText("Fetching time series %s of %s" % \
(i+1,N))
print self, "Fetching time series ", i+1, " of ", N
qApp.processEvents()
ingredient = ingredientList[i]
if progress.wasCanceled():
for ingredient in ingredientList[i:len(ingredientList)]:
ingredient.error = 1
badIngredients.append(ingredient)
break
try:
ingredient.getTimeSeries (win)
ingredient.error = 0
except:
#Handle Exception here
# Create a badIngredient list here
for ingredient in badIngredients:
self.deleteIngredient(ingredient)
finally:
progress.setValue(N)
progress.close()
self.callWhenFree (self, self.chartChanged, remove=True)
self.unlock()
self.emit (SIGNAL("dataChanged"))
self.fetchEdition = self.chartEdition
end = time.clock()
print "Data Fetched in %s sec" %(end-start)
РЕДАКТИРОВАТЬ: при выполнении этого цикла, с течением времени диалог прогресса становится все медленнее и медленнее. Но происходит много других вещей, таких как создание огромной таблицы для этих данных и больше объектов Qt. Кроме того, рисование диаграммы QGraphicsItem становится медленнее. В настоящее время,
Я прокомментировал qApp.processEvent () для целей тестирования, в списке ошибок Qt говорится, что QProgressDialog.setValue внутренне вызывает processEvents, поэтому мне не нужно явно вызывать. Также существует проблема зависания, когда приложение просто зависает в этом диалоговом окне прогресса и должно его убить.
Я использовал objgraph http://mg.pov.lt/objgraph/, чтобы получить 50 самых верхних объектов в памяти
Это то, что я получаю, когда открываю приложение в первый раз
tuple 16243
dict 6325
function 4220
instance 3814
QTreeWidgetItem 2849
wrapper_descriptor 2642
weakref 1447
getset_descriptor 1387
list 934
method_descriptor 815
builtin_function_or_method 805
wrappertype 660
type 652
classobj 267
module 235
member_descriptor 181
QAction 154
instancemethod 47
property 36
frame 34
QWidget 33
QColor 33
QVBoxLayout 27
_Condition 20
QLabel 18
QMenu 17
QToolButton 14
QTableWidgetItem 13
QGridLayout 13
SplitResult 13
QTimer 11
TypeInfo 10
classmethod_descriptor 10
QComboBox 9
QLineEdit 9
QCheckBox 9
QSpacerItem 8
QGroupBox 7
PenStyle 6
set 6
ChartViewAction 6
QHBoxLayout 6
MouseButton 6
QRadioButton 5
QActionGroup 5
QtMsgType 5
Thread 4
QPushButton 4
QToolBar 4
staticmethod 4
После запуска кода, который может быть утечка, самые верхние 30 объектов в памяти.
tuple 19948
QTableWidgetItem 9298
dict 7562
function 4220
instance 4157
QTreeWidgetItem 2849
wrapper_descriptor 2788
QGraphicsRectItem 2246
weakref 1527
getset_descriptor 1392
list 1198
QGraphicsLineItem 825
method_descriptor 816
QGraphicsTextItem 812
builtin_function_or_method 811
QColor 780
DQEllipse 748
wrappertype 660
type 652
QAction 280
classobj 267
module 235
member_descriptor 189
instancemethod 110
dqComboBoxTableItem 66
property 36
frame 35
QWidget 33
QVBoxLayout 27
GlobalColor 24
QTableWidgetItems должен находиться в памяти. В настоящее время я тестирую это приложение с отключением gc. Большинство объектов, которые я вижу, создаются и хранятся в памяти, такие как QGraphicsLineItem, QGraphicsRectItem и т. Д. Когда я создаю новые объекты, эти объекты перезаписываются новыми объектами, что приводит к удалению ссылок на старый.
Каковы другие средства тестирования утечки памяти?