Source code for bgdev.tools.performance

"""Evaluation Toolkit.

:created: 03/06/2019
:author: Benoit GIELLY <benoit.gielly@gmail.com>
"""
import cProfile
import logging
import os

from maya import cmds, mel
from maya.debug import emPerformanceTest  # type: ignore

LOG = logging.getLogger(__name__)


[docs]def frames_per_second( iterations=3, start=1001, frames=100, viewports=("viewport2"), meshes_only=True, outfile=None, ): """Evaluate the framePerSecond in the current scene. Args: iterations (int): Amount of time the timeline should run. start (int): Start frame. frames (int): The amount of frames to run. viewports (list): Select the viewports you want to evaluate on. Possible values are "legacy" and "viewport2". meshes_only (bool): Hides everything but meshes in the viewport. outfile (bool or str): Save the output fps in the given txt file. If `True` is passed, query the current scene path and save the log next to it (Useful when benchmarking multiple scenes in a loop). Returns: float: The evaluated frame per seconds as a float number. """ # override Maya's emPerformanceTest method to work with custom viewports def switch_maya_viewport(new_mode): """Override Maya's method.""" if new_mode == "legacy": mel.eval( 'setRendererInModelPanel "base_OpenGL_Renderer" modelPanel4' ) elif new_mode == "viewport2": mel.eval('setRendererInModelPanel "vp2Renderer" modelPanel4') else: raise NameError( "Selected viewport {!r} not found!".format(new_mode) ) emPerformanceTest.switchMayaViewport = switch_maya_viewport # start the FPS evaluation tool if not isinstance(viewports, list): viewports = [viewports] # set the frame range if frames <= 10: LOG.warning( "End frame must be higher than start frame. Using 10 as a minimum." ) frames = 10 end = start + frames cmds.playbackOptions( edit=True, animationStartTime=start, minTime=start, animationEndTime=end, maxTime=end, ) cmds.currentTime(start) # enable GPU acceleration mel.eval("turnOnOpenCLEvaluatorActive();") # disable color management color_management = cmds.colorManagementPrefs(query=True, cmEnabled=True) cmds.colorManagementPrefs(edit=True, cmEnabled=False) # hide all nodes but meshes in viewport if meshes_only: panels = cmds.getPanel(type="modelPanel") for each in panels: cmds.modelEditor(each, edit=True, allObjects=False) cmds.modelEditor(each, edit=True, polymeshes=True) cmds.refresh() # setup the mayaPerformanceTest emPerformanceTest.EMPERFORMANCE_PLAYBACK_MAX = frames options = emPerformanceTest.emPerformanceOptions() options.setViewports(viewports) options.setTestTypes([options.TEST_PLAYBACK]) options.setReportProgress(True) options.iterationCount = iterations options.evalModes = ["emp"] # run the performanceTest # (code snippet below from maya source files >>> BLACK MAGIC) csv = emPerformanceTest.emPerformanceTest(None, "csv", options) row_dictionary = dict(zip(csv[0].split(",")[1:], csv[1].split(",")[1:])) start_title, end_title, frame = "Start Frame", "End Frame", 0.0 if start_title in row_dictionary and end_title in row_dictionary: frame = ( float(row_dictionary[end_title]) - float(row_dictionary[start_title]) + 1.0 ) # build up message string msg = "Playback Speeds\n {:=>17}".format("\n") for viewport in viewports: mode = "{} - Parallel".format(viewport) title = "{} Playback EMP Avg".format(viewport) playback_time = float(row_dictionary[title]) rate = playback_time if frame == 0.0 else frame / playback_time msg += " {} = {} fps\n".format(mode, rate) LOG.info("\n %s", msg) # re-enable color management cmds.colorManagementPrefs(edit=True, cmEnabled=color_management) # generate a text file to log out the evaluation result if outfile is True: scene = cmds.file(query=True, sceneName=True) outfile = "{}.txt".format(os.path.splitext(scene)[0]) if scene else "" if outfile: os.system("echo '{}' > {}".format(msg, outfile)) LOG.info("FPS logs saved into %s", outfile) return rate
[docs]class Profiler(object): """Create a python profiler to check for code usage. Example: :: import bgdev.tools.performance profiler = bgdev.tools.performance.Profiler() profiler.start() # run python code profiler.stop() """
[docs] def __init__(self): self.profiler = cProfile.Profile(subcalls=False)
[docs] def start(self): """Enable the profiler.""" self.profiler.enable()
[docs] def stop(self, sort="time"): """Stop the profiler and print restult. Args: sort(str): Sort the stats with given value. """ self.profiler.disable() self.stats(sort)
[docs] def stats(self, sort="tottime"): """Print the profiler stats. Args: sort(str): Sort the stats with given value. """ self.profiler.print_stats(sort=sort)