Чрезмерная сборка мусора? - PullRequest
0 голосов
/ 01 марта 2011

Детали приложения: приложение 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 и т. Д. Когда я создаю новые объекты, эти объекты перезаписываются новыми объектами, что приводит к удалению ссылок на старый. Каковы другие средства тестирования утечки памяти?

1 Ответ

0 голосов
/ 01 марта 2011

Вы можете попробовать отключить сборку мусора, чтобы проверить свою теорию:

gc.disable()

или еще лучше:

gc.set_debug(gc.DEBUG_LEAK)

См. соответствующую страницу вСсылка на Python для более.

...