Implement optional profiling for export

This commit is contained in:
Moritz Brückner 2020-10-31 01:09:33 +01:00
parent eb460a8e75
commit 0f3233d829
3 changed files with 44 additions and 2 deletions

View file

@ -30,6 +30,7 @@ import arm.material.cycles as cycles
import arm.material.make as make_material
import arm.material.mat_batch as mat_batch
import arm.utils
import arm.profiler
@unique
@ -127,7 +128,6 @@ class ArmoryExporter:
self.world_array = []
self.particle_system_array = {}
# `True` if there is at least one spawned camera in the scene
self.camera_spawned = False
@ -150,7 +150,8 @@ class ArmoryExporter:
"""Exports the given scene to the given file path. This is the
function that is called in make.py and the entry point of the
exporter."""
cls(context, filepath, scene, depsgraph).execute()
with arm.profiler.Profile('profile_exporter.prof', arm.utils.get_pref_or_default('profile_exporter', False)):
cls(context, filepath, scene, depsgraph).execute()
@classmethod
def preprocess(cls):

35
blender/arm/profiler.py Normal file
View file

@ -0,0 +1,35 @@
import cProfile
import os
import pstats
import arm.log as log
import arm.utils as utils
class Profile:
"""Context manager for profiling the enclosed code when the given condition is true.
The output file is stored in the SDK directory and can be opened by tools such as SnakeViz.
"""
def __init__(self, filename_out: str, condition: bool):
self.filename_out = filename_out
self.condition = condition
self.pr = cProfile.Profile()
def __enter__(self):
if self.condition:
self.pr.enable()
log.debug("Profiling started")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if self.condition:
self.pr.disable()
log.debug("Profiling finished")
profile_path = os.path.join(utils.get_sdk_path(), self.filename_out)
with open(profile_path, 'w') as profile_file:
stats = pstats.Stats(self.pr, stream=profile_file)
stats.dump_stats(profile_path)
return False

View file

@ -4,6 +4,7 @@ import os
import platform
import re
import subprocess
from typing import Any
import webbrowser
import shlex
@ -226,6 +227,11 @@ def get_relative_paths():
addon_prefs = get_arm_preferences()
return False if not hasattr(addon_prefs, 'relative_paths') else addon_prefs.relative_paths
def get_pref_or_default(prop_name: str, default: Any) -> Any:
"""Return the preference setting for prop_name, or the value given as default if the property does not exist."""
addon_prefs = get_arm_preferences()
return default if not hasattr(addon_prefs, prop_name) else getattr(addon_prefs, prop_name)
def get_node_path():
if get_os() == 'win':
return get_sdk_path() + '/nodejs/node.exe'