def _loadHeap(self): fileName = QFileDialog.getOpenFileName(self, u"打开Tcmalloc Heap文件", u"", u"Heap文件(*.heap)") if fileName: self.heapFile = fileName self.parser = HeapProfileParser() self.parser.parseIt(fileName) print '==== LibInfo ====' for lib in self.parser.libInfo: print lib # print '\n==== AddressInfo ====' # for addr in self.parser.addressInfo: # print addr self.addrTbl = HeapProfileAddressTable(self.parser) self.addrTbl.buildTable() print len(self.parser.addressInfo), len(self.parser.addressInfo[0]) # cnt = 0 # for x in self.parser.addressInfo: # cnt += 1 # if cnt > 5: # break # print '------------------------------------------------' # for addr in x[1]: # print self.addrTbl.addr2name(addr) self._buildStackTree() self._updateUI()
class Main(QMainWindow, main_ui.Ui_MainWindow): def __init__(self, parent=None): super(Main, self).__init__(parent) self._tagList = config.Tags self.stackTree = StackTree() self.setupUi(self) self.treeHeap.setColumnWidth(0, 300) self.treeHeap.setColumnWidth(1, 100) self.treeHeap.setColumnWidth(2, 250) self.treeHeap.setColumnWidth(3, 100) self.treeHeap.setColumnWidth(4, 100) self.treeHeap.setColumnWidth(5, 100) self.treeHeap.setColumnWidth(6, 100) self._initEvents() def _initEvents(self): self.treeHeap.setItemDelegate(TagDelegate(self)) self.treeContextMenu = QMenu(self) self.action_addTag = QAction('Add Tag', self.treeContextMenu) self.action_addTag.triggered.connect(self._addTag) self.treeHeap.addAction(self.action_addTag) self.treeHeap.setContextMenuPolicy(Qt.ActionsContextMenu) self.action_LoadHeap.triggered.connect(self._loadHeap) self.action_SaveTag.triggered.connect(self._saveTag) self.action_AddTag.triggered.connect(self._addTag) self.action_LoadTag.triggered.connect(self._loadTag) self.btnNewTag.clicked.connect(self._addTag) def _addTag(self): newtag = self.editTagName.text() oldset = set(self._tagList) oldset.add(newtag) self._tagList = list(oldset) self._updateTable() def _loadTag(self): fileName = QFileDialog.getOpenFileName(self, u"打开tag文件", u"", u"Tag文件(*.tagfile)") if fileName: with open(fileName, 'r') as fp: self.taggedStackTree = cPickle.loads(fp.read()) self._updateTags() def _updateTags(self): if self.stackTree.empty() or self.taggedStackTree.empty(): return self._tagList = self.stackTree.syncTagsFrom(self.taggedStackTree) self._updateUI() def _checkTag(self, key, tag): curNode = self.root while True: childCount = curNode.childCount() nextNode = None for i in xrange(childCount): child = curNode.child(i) def _saveTag(self): fileName = QFileDialog.getSaveFileName(self, u"保存tag文件", u"", u"Tag文件(*.tagfile)") if fileName: with open(fileName, 'w') as fp: fp.write(cPickle.dumps(self.stackTree)) def _loadHeap(self): fileName = QFileDialog.getOpenFileName(self, u"打开Tcmalloc Heap文件", u"", u"Heap文件(*.heap)") if fileName: self.heapFile = fileName self.parser = HeapProfileParser() self.parser.parseIt(fileName) print '==== LibInfo ====' for lib in self.parser.libInfo: print lib # print '\n==== AddressInfo ====' # for addr in self.parser.addressInfo: # print addr self.addrTbl = HeapProfileAddressTable(self.parser) self.addrTbl.buildTable() print len(self.parser.addressInfo), len(self.parser.addressInfo[0]) # cnt = 0 # for x in self.parser.addressInfo: # cnt += 1 # if cnt > 5: # break # print '------------------------------------------------' # for addr in x[1]: # print self.addrTbl.addr2name(addr) self._buildStackTree() self._updateUI() def onTagChanged(self): self._updateTable() def itemDataChanged(self, topLeft, bottomRight): if topLeft.column() == 1 and bottomRight.column() == 1: print 'itemChanged', topLeft.column(), topLeft.row( ), bottomRight.column(), bottomRight.row() def _buildStackTree(self): self.stackTree.clear() for sample in self.parser.addressInfo: liveCount, liveBytes, sumCount, sumBytes = sample[0] stack = sample[1] stack_depth = len(stack) depth = 0 curNode = self.stackTree.root while True: addr = stack[depth] funcName, fileName, lineNo, libName = self.addrTbl.addr2name( addr) addrKey = (funcName, fileName, lineNo, libName) childCount = curNode.childCount() nextNode = None for i in xrange(childCount): child = curNode.child(i) userKey = (child.funcName, child.fileName, child.lineNo, child.libName) if userKey == addrKey: nextNode = child if not nextNode: nextNode = StackNode(curNode, funcName, fileName, lineNo, libName, liveCount, liveBytes, sumCount, sumBytes) curNode.append(nextNode) else: nextNode.liveCount += liveCount nextNode.liveBytes += liveBytes nextNode.sumCount += sumCount nextNode.sumBytes += sumBytes curNode = nextNode depth += 1 if depth >= stack_depth: break def _addStackNodeUI(self, parentTreeItem, stacknode): newItem = QTreeWidgetItem(parentTreeItem) newItem.setFlags(newItem.flags() | Qt.ItemIsEditable) newItem.setText(0, stacknode.funcName) # function name newItem.setData(0, Qt.UserRole, QVariant(stacknode)) # save #newItem.setData(1, Qt.UserRole, self._tagList) # tag newItem.setText(1, stacknode.tag) moduleName = os.path.split(stacknode.libName)[1] newItem.setText( 2, '[%s]%s, Line:%d' % (moduleName, stacknode.fileName, stacknode.lineNo)) # code line newItem.setText(3, str(stacknode.liveCount)) newItem.setText(4, str(stacknode.liveBytes)) newItem.setText(5, str(stacknode.sumCount)) newItem.setText(6, str(stacknode.sumBytes)) childCount = stacknode.childCount() for i in xrange(childCount): child = stacknode.child(i) self._addStackNodeUI(newItem, child) def _updateTable(self): tagValues = self.stackTree.scanTagValues(self._tagList) tagCount = len(self._tagList) self.tableWidget.setColumnCount(6) self.tableWidget.setRowCount(tagCount + 2) sumValues = [0, 0, 0, 0] totalValues = self.stackTree.getTotalValues() for i in xrange(tagCount): tag = self._tagList[i] sumValues[0] += tagValues[tag][0] sumValues[1] += tagValues[tag][1] sumValues[2] += tagValues[tag][2] sumValues[3] += tagValues[tag][3] self.tableWidget.setItem(i, 0, QTableWidgetItem(tag)) self.tableWidget.setItem(i, 1, QTableWidgetItem(str(tagValues[tag][0]))) self.tableWidget.setItem( i, 2, QTableWidgetItem('%.4fM' % (tagValues[tag][1] / 1024.0 / 1024.0))) self.tableWidget.setItem(i, 3, QTableWidgetItem(str(tagValues[tag][2]))) self.tableWidget.setItem( i, 4, QTableWidgetItem('%.4fM' % (tagValues[tag][3] / 1024.0 / 1024.0))) self.tableWidget.setItem( i, 5, QTableWidgetItem('%.2f%%' % (tagValues[tag][1] * 100.0 / totalValues[1]))) remainValues = [(totalValues[i] - sumValues[i]) for i in xrange(4)] self.tableWidget.setItem(tagCount, 0, QTableWidgetItem('<Remain>')) self.tableWidget.setItem(tagCount, 1, QTableWidgetItem(str(remainValues[0]))) self.tableWidget.setItem( tagCount, 2, QTableWidgetItem('%.4fM' % (remainValues[1] / 1024.0 / 1024.0))) self.tableWidget.setItem(tagCount, 3, QTableWidgetItem(str(remainValues[2]))) self.tableWidget.setItem( tagCount, 4, QTableWidgetItem('%.4fM' % (remainValues[3] / 1024.0 / 1024.0))) self.tableWidget.setItem( tagCount, 5, QTableWidgetItem('%.2f%%' % (remainValues[1] * 100.0 / totalValues[1]))) self.tableWidget.setItem(tagCount + 1, 0, QTableWidgetItem('<Total>')) self.tableWidget.setItem(tagCount + 1, 1, QTableWidgetItem(str(totalValues[0]))) self.tableWidget.setItem( tagCount + 1, 2, QTableWidgetItem('%.4fM' % (totalValues[1] / 1024.0 / 1024.0))) self.tableWidget.setItem(tagCount + 1, 3, QTableWidgetItem(str(remainValues[2]))) self.tableWidget.setItem( tagCount + 1, 4, QTableWidgetItem('%.4fM' % (totalValues[3] / 1024.0 / 1024.0))) self.tableWidget.setItem( tagCount + 1, 5, QTableWidgetItem('%.2f%%' % (totalValues[1] * 100.0 / totalValues[1]))) def _updateUI(self): self.treeHeap.clear() self.root = QTreeWidgetItem(self.treeHeap) self.root.setText(0, "root") self.treeHeap.addTopLevelItem(self.root) for child in self.stackTree.root.childs: self._addStackNodeUI(self.root, child) self._updateTable()
class Main(QMainWindow, main_ui.Ui_MainWindow): def __init__(self, parent=None): super(Main, self).__init__(parent) self._tagList = config.Tags self.stackTree = StackTree() self.setupUi(self) self.treeHeap.setColumnWidth(0,300) self.treeHeap.setColumnWidth(1,100) self.treeHeap.setColumnWidth(2,250) self.treeHeap.setColumnWidth(3,100) self.treeHeap.setColumnWidth(4,100) self.treeHeap.setColumnWidth(5,100) self.treeHeap.setColumnWidth(6,100) self._initEvents() def _initEvents(self): self.treeHeap.setItemDelegate(TagDelegate(self)) self.treeContextMenu = QMenu(self) self.action_addTag = QAction('Add Tag', self.treeContextMenu) self.action_addTag.triggered.connect(self._addTag) self.treeHeap.addAction(self.action_addTag) self.treeHeap.setContextMenuPolicy(Qt.ActionsContextMenu) self.action_LoadHeap.triggered.connect(self._loadHeap) self.action_SaveTag.triggered.connect(self._saveTag) self.action_AddTag.triggered.connect(self._addTag) self.action_LoadTag.triggered.connect(self._loadTag) self.btnNewTag.clicked.connect(self._addTag) def _addTag(self): newtag = self.editTagName.text() oldset = set(self._tagList) oldset.add(newtag) self._tagList = list(oldset) self._updateTable() def _loadTag(self): fileName = QFileDialog.getOpenFileName(self, u"打开tag文件", u"", u"Tag文件(*.tagfile)") if fileName: with open(fileName, 'r') as fp: self.taggedStackTree = cPickle.loads(fp.read()) self._updateTags() def _updateTags(self): if self.stackTree.empty() or self.taggedStackTree.empty(): return self._tagList = self.stackTree.syncTagsFrom(self.taggedStackTree) self._updateUI() def _checkTag(self, key, tag): curNode = self.root while True: childCount = curNode.childCount() nextNode = None for i in xrange(childCount): child = curNode.child(i) def _saveTag(self): fileName = QFileDialog.getSaveFileName(self, u"保存tag文件", u"", u"Tag文件(*.tagfile)") if fileName: with open(fileName, 'w') as fp: fp.write(cPickle.dumps(self.stackTree)) def _loadHeap(self): fileName = QFileDialog.getOpenFileName(self, u"打开Tcmalloc Heap文件", u"", u"Heap文件(*.heap)") if fileName: self.heapFile = fileName self.parser = HeapProfileParser() self.parser.parseIt(fileName) print '==== LibInfo ====' for lib in self.parser.libInfo: print lib # print '\n==== AddressInfo ====' # for addr in self.parser.addressInfo: # print addr self.addrTbl = HeapProfileAddressTable(self.parser) self.addrTbl.buildTable() print len(self.parser.addressInfo), len(self.parser.addressInfo[0]) # cnt = 0 # for x in self.parser.addressInfo: # cnt += 1 # if cnt > 5: # break # print '------------------------------------------------' # for addr in x[1]: # print self.addrTbl.addr2name(addr) self._buildStackTree() self._updateUI() def onTagChanged(self): self._updateTable() def itemDataChanged(self, topLeft, bottomRight): if topLeft.column() == 1 and bottomRight.column() == 1: print 'itemChanged', topLeft.column(), topLeft.row(), bottomRight.column(), bottomRight.row() def _buildStackTree(self): self.stackTree.clear() for sample in self.parser.addressInfo: liveCount, liveBytes, sumCount, sumBytes = sample[0] stack = sample[1] stack_depth = len(stack) depth = 0 curNode = self.stackTree.root while True: addr = stack[depth] funcName, fileName, lineNo, libName = self.addrTbl.addr2name(addr) addrKey = (funcName, fileName, lineNo, libName) childCount = curNode.childCount() nextNode = None for i in xrange(childCount): child = curNode.child(i) userKey = (child.funcName, child.fileName, child.lineNo, child.libName) if userKey == addrKey: nextNode = child if not nextNode: nextNode = StackNode(curNode, funcName, fileName, lineNo, libName, liveCount, liveBytes, sumCount, sumBytes) curNode.append(nextNode) else: nextNode.liveCount += liveCount nextNode.liveBytes += liveBytes nextNode.sumCount += sumCount nextNode.sumBytes += sumBytes curNode = nextNode depth += 1 if depth >= stack_depth: break def _addStackNodeUI(self, parentTreeItem, stacknode): newItem = QTreeWidgetItem(parentTreeItem) newItem.setFlags( newItem.flags() | Qt.ItemIsEditable ) newItem.setText(0, stacknode.funcName) # function name newItem.setData(0, Qt.UserRole, QVariant(stacknode)) # save #newItem.setData(1, Qt.UserRole, self._tagList) # tag newItem.setText(1, stacknode.tag) moduleName = os.path.split(stacknode.libName)[1] newItem.setText(2, '[%s]%s, Line:%d'%(moduleName, stacknode.fileName, stacknode.lineNo)) # code line newItem.setText(3, str(stacknode.liveCount)) newItem.setText(4, str(stacknode.liveBytes)) newItem.setText(5, str(stacknode.sumCount)) newItem.setText(6, str(stacknode.sumBytes)) childCount = stacknode.childCount() for i in xrange(childCount): child = stacknode.child(i) self._addStackNodeUI( newItem, child ) def _updateTable(self): tagValues = self.stackTree.scanTagValues(self._tagList) tagCount = len(self._tagList) self.tableWidget.setColumnCount(6) self.tableWidget.setRowCount(tagCount+2) sumValues = [0, 0, 0, 0] totalValues = self.stackTree.getTotalValues() for i in xrange(tagCount): tag = self._tagList[i] sumValues[0] += tagValues[tag][0] sumValues[1] += tagValues[tag][1] sumValues[2] += tagValues[tag][2] sumValues[3] += tagValues[tag][3] self.tableWidget.setItem(i, 0, QTableWidgetItem(tag)) self.tableWidget.setItem(i, 1, QTableWidgetItem(str(tagValues[tag][0]))) self.tableWidget.setItem(i, 2, QTableWidgetItem('%.4fM'%(tagValues[tag][1]/1024.0/1024.0))) self.tableWidget.setItem(i, 3, QTableWidgetItem(str(tagValues[tag][2]))) self.tableWidget.setItem(i, 4, QTableWidgetItem('%.4fM'%(tagValues[tag][3]/1024.0/1024.0))) self.tableWidget.setItem(i, 5, QTableWidgetItem('%.2f%%'%(tagValues[tag][1]*100.0/totalValues[1]))) remainValues = [ (totalValues[i] - sumValues[i]) for i in xrange(4) ] self.tableWidget.setItem(tagCount, 0, QTableWidgetItem('<Remain>')) self.tableWidget.setItem(tagCount, 1, QTableWidgetItem(str(remainValues[0]))) self.tableWidget.setItem(tagCount, 2, QTableWidgetItem('%.4fM'%(remainValues[1]/1024.0/1024.0))) self.tableWidget.setItem(tagCount, 3, QTableWidgetItem(str(remainValues[2]))) self.tableWidget.setItem(tagCount, 4, QTableWidgetItem('%.4fM'%(remainValues[3]/1024.0/1024.0))) self.tableWidget.setItem(tagCount, 5, QTableWidgetItem('%.2f%%'%(remainValues[1]*100.0/totalValues[1]))) self.tableWidget.setItem(tagCount+1, 0, QTableWidgetItem('<Total>')) self.tableWidget.setItem(tagCount+1, 1, QTableWidgetItem(str(totalValues[0]))) self.tableWidget.setItem(tagCount+1, 2, QTableWidgetItem('%.4fM'%(totalValues[1]/1024.0/1024.0))) self.tableWidget.setItem(tagCount+1, 3, QTableWidgetItem(str(remainValues[2]))) self.tableWidget.setItem(tagCount+1, 4, QTableWidgetItem('%.4fM'%(totalValues[3]/1024.0/1024.0))) self.tableWidget.setItem(tagCount+1, 5, QTableWidgetItem('%.2f%%'%(totalValues[1]*100.0/totalValues[1]))) def _updateUI(self): self.treeHeap.clear() self.root = QTreeWidgetItem(self.treeHeap) self.root.setText(0, "root") self.treeHeap.addTopLevelItem(self.root) for child in self.stackTree.root.childs: self._addStackNodeUI(self.root, child) self._updateTable()