过多的垃圾收集?

时间:2011-03-01 15:36:44

标签: collections garbage-collection pyqt

应用程序详细信息:pyQt应用程序,Qt 4.4和python 2.5

问题:随着时间的推移(使用应用程序很长时间没有关闭),应用程序有时会变慢。我尝试了大部分的分析应用程序,但没有找到任何重要的指出任何问题。

我的应用程序使用QTabWidget在不同的选项卡中创建多个表。因此,为了加快Tab切换,我只构造一次表并将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的bug列表中它说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 :(得分:0)

你可以尝试关闭垃圾收集来测试你的理论:

gc.disable()

或更好:

gc.set_debug(gc.DEBUG_LEAK)

有关详细信息,请参阅python参考中的the relevant page