Source code for nukescripts.cache

# Copyright (c) 2009 The Foundry Visionmongers Ltd.  All Rights Reserved.

import nuke_internal as nuke
from nuke import memory2 as memory

from PySide2.QtWidgets import QApplication
from PySide2.QtWidgets import QDialog
from PySide2.QtWidgets import QLabel

from PySide2.QtCore import Qt


[docs]def clearAllCaches(): """ Clears all caches. The disk cache, viewer playback cache and memory buffers. """ nuke.clearDiskCache() nuke.clearRAMCache() nuke.clearBlinkCache() memory.clearUsage()
[docs]def humanReadable(numBytes): """ Returns a string containing the number of bytes and the ISO/IEC units used. """ def formatBytes(numBytes, unit): return "{:.2f} {}B".format(numBytes, unit) units = (' ', 'Ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi', 'Yi') if numBytes < 0: return formatBytes(0, units[0]) for unit in units[:-1]: if numBytes < 1024: return formatBytes(numBytes, unit) numBytes /= 1024 return formatBytes(numBytes, units[-1])
[docs]class ValueLabel(QLabel): def __init__(self, text): QLabel.__init__(self, text) self.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
[docs]class ReportTree(QDialog): def __init__(self): from PySide2.QtWidgets import QVBoxLayout QDialog.__init__(self, parent=QApplication.activeWindow(), f=Qt.Tool) self.setWindowTitle('Buffer Report') self.resize(800, 400) layout = QVBoxLayout() self.headerLayout = self.createHeaderLayout() self.updateUsageLabels() layout.addLayout(self.headerLayout) self.tree = self.createTree() self.updateTreeContents() layout.addWidget(self.tree) layout.addWidget(self.createButtonBox()) self.setLayout(layout) def createHeaderLayout(self): from PySide2.QtWidgets import QGridLayout layout = QGridLayout() layout.addWidget(QLabel("Usage"), 0, 0) layout.addWidget(QLabel("Max Usage"), 1, 0) layout.addWidget(QLabel("Total Memory"), 2, 0) self.labels = [] total = min(memory.totalRAM(), memory.totalVM()) layout.addWidget(ValueLabel(humanReadable(total)), 2, 1) layout.setColumnStretch(3, 1) return layout def updateUsageLabels(self): if self.labels: for label in self.labels: self.headerLayout.removeWidget(label) label.hide() del label self.labels = [] self.labels.append(ValueLabel(humanReadable(memory.usage()))) self.headerLayout.addWidget(self.labels[0], 0, 1) percentage = (memory.usage() / memory.maxUsage()) * 100.0 self.labels.append(ValueLabel("{:.2f} %".format(percentage))) self.headerLayout.addWidget(self.labels[1], 0, 2) self.labels.append(ValueLabel(humanReadable(memory.maxUsage()))) self.headerLayout.addWidget(self.labels[2], 1, 1) percentage = nuke.toNode("preferences")["CacheLimit"].value() self.labels.append(ValueLabel("{:.2f} %".format(percentage))) self.headerLayout.addWidget(self.labels[3], 1, 2) def createTree(self): from PySide2.QtWidgets import QTreeWidget from PySide2.QtWidgets import QHeaderView from PySide2.QtWidgets import QAbstractItemView from PySide2.QtWidgets import QSizePolicy tree = QTreeWidget() headers = ["Name", "Size", "User", "Data"] tree.setColumnCount(len(headers)) tree.setHeaderLabels(headers) tree.header().setSectionResizeMode(QHeaderView.Fixed) tree.setSelectionBehavior(QAbstractItemView.SelectRows) tree.setAlternatingRowColors(True) tree.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) return tree def updateTreeContents(self): from PySide2.QtWidgets import QTreeWidgetItem from operator import itemgetter def sumTotalBytes(items): return sum([item["bytes"] for item in items]) self.info = memory.info() info = list(self.info.items()) info.sort(key=lambda x: sumTotalBytes(x[1]), reverse=True) for name, items in info: branch = QTreeWidgetItem(self.tree) branch.setText(0, name) branch.setText(1, humanReadable(sumTotalBytes(items))) branch.setTextAlignment(1, Qt.AlignRight | Qt.AlignVCenter) items.sort(key=itemgetter("bytes"), reverse=True) for item in items: stem = QTreeWidgetItem(branch) stem.setText(0, item["name"]) stem.setText(1, humanReadable(item["bytes"])) stem.setTextAlignment(1, Qt.AlignRight | Qt.AlignVCenter) for user, data in item.items(): if user == "name" or user == "bytes": continue leaf = QTreeWidgetItem(stem) leaf.setText(2, user) leaf.setText(3, data) self.expandTree() for i in range(self.tree.columnCount()): self.tree.resizeColumnToContents(i) self.collapseTree() def createButtonBox(self): from PySide2.QtWidgets import QDialogButtonBox buttonBox = QDialogButtonBox() def addButton(name, function, tip=None): from PySide2.QtWidgets import QPushButton button = QPushButton(name) button.clicked.connect(function) if tip: button.setToolTip(tip) buttonBox.addButton(button, QDialogButtonBox.ActionRole) addButton("Expand All", self.expandTree) addButton("Collapse All", self.collapseTree) addButton("Update", self.updateContents) addButton("Save", self.save, "Saves the memory info structure to a Json file.") return buttonBox def expandTree(self): self.expand(True) def collapseTree(self): self.expand(False) def __recursiveExpand(self, item, expand): for i in range(item.childCount()): child = item.child(i) self.__recursiveExpand(child, expand) item.setExpanded(expand) def expand(self, expand): for i in range(self.tree.topLevelItemCount()): item = self.tree.topLevelItem(i) self.__recursiveExpand(item, expand) def updateContents(self): self.updateUsageLabels() self.tree.clear() self.updateTreeContents() def save(self): from PySide2.QtWidgets import QFileDialog from json import dump path = QFileDialog.getSaveFileName( parent=self, caption="Save as", filter="Json (*.json)") if path is None: return dump(self.info, open(path[0], 'w'), indent=2)
[docs]def showReportDialog(): """ Creates a tree containing memory information from tracked allocations. """ for widget in QApplication.topLevelWidgets(): if isinstance(widget, ReportTree): widget.updateContents() widget.show() widget.windowHandle().requestActivate() return dialog = ReportTree() dialog.show()