如何分析 QGIS Python 插件的性能?
How to profile performance in a QGIS Python plugin?
是否可以使用 kernprof.py、line_profiler.py 或类似的工具来配置 QGIS 插件?我不能 运行 QGIS 之外的插件,因为插件需要来自 QGIS 的状态并且会调用 QGIS API.
似乎我可以修改插件的初始化程序以调用 kernprof,回调插件并一直传递状态,但我无法理解它。
有没有人有过从其他工具中 运行 使用 Python 探查器的经验?
我使用了一种更简单的方法来使用 cProfile 分析我的插件。在插件的主要 class 构造函数中(在 classFactory 中返回),我使用了以下代码:
self.pr = cProfile.Profile()
self.pr.enable()
并在 class 的卸载方法中或任何需要打印配置文件统计信息的地方:
self.pr.disable()
s = io.StringIO()
sortby = SortKey.CUMULATIVE
ps = pstats.Stats(self.pr, stream=s).sort_stats(sortby)
ps.print_stats()
记得使用以下代码进行导入:
import cProfile, pstats, io
from pstats import SortKey
可以在 QGIS 中使用 line_profiler 而 运行 你的脚本。
您需要将它与其他导入一起导入到插件的主文件中,然后在主文件 class 之前添加 profile = line_profiler.LineProfiler()
,在主文件之前添加装饰器 @profile
函数进行分析,最后在函数的 return 之前添加 profile.print_stats(stream=stream)
。
我想还有其他方法可以做到,但这是我发现的方法对我来说足够好。
下面是处理插件的示例:
import os
import line_profiler
profile = line_profiler.LineProfiler()
class processingScriptExample(QgsProcessingAlgorithm):
INPUT_directory = 'INPUT_directory'
def initAlgorithm(self, config):
self.addParameter(QgsProcessingParameterNumber(self.INPUT_directory,
self.tr('Output directory'),
QgsProcessingParameterFile.Folder))
@profile
def processAlgorithm(self, parameters, context, feedback):
directory = self.parameterAsInt(parameters, self.INPUT_directory, context)
ls = []
for ii in range(1000000):
ls.append(ii)
ls = [ii for ii in range(1000000)]
path_profiling = os.path.join(directory, "line_profiling.txt")
with open(path_profiling, 'w') as stream:
profile.print_stats(stream=stream)
return {'Profiling file': path_profiling}
生成的文件:
Timer unit: 1e-07 s
Total time: 1.31260 s
File: C:\OSGeo4W\profiles\default/python/plugins\test\algo_test.py
Function: processAlgorithm at line 70
Line # Hits Time Per Hit % Time Line Contents
==============================================================
70 @profile
71 def processAlgorithm(self, parameters, context, feedback):
72 1 248.0 248.0 0.0 directory = self.parameterAsInt(parameters, self.INPUT_directory, context)
73
74 1 8.0 8.0 0.0 ls = []
75 1000001 5054594.0 5.1 38.5 for ii in range(1000000):
76 1000000 6633146.0 6.6 50.5 ls.append(ii)
77
78 1 1418416.0 1418416.0 10.8 ls = [ii for ii in range(1000000)]
79
80 1 561.0 561.0 0.0 path_profiling = os.path.join(directory, "line_profiling.txt")
81 1 19001.0 19001.0 0.1 with open(path_profiling, 'w') as stream:
82 profile.print_stats(stream=stream)
83
84 return {"Profiling file":path_profiling}
是否可以使用 kernprof.py、line_profiler.py 或类似的工具来配置 QGIS 插件?我不能 运行 QGIS 之外的插件,因为插件需要来自 QGIS 的状态并且会调用 QGIS API.
似乎我可以修改插件的初始化程序以调用 kernprof,回调插件并一直传递状态,但我无法理解它。
有没有人有过从其他工具中 运行 使用 Python 探查器的经验?
我使用了一种更简单的方法来使用 cProfile 分析我的插件。在插件的主要 class 构造函数中(在 classFactory 中返回),我使用了以下代码:
self.pr = cProfile.Profile()
self.pr.enable()
并在 class 的卸载方法中或任何需要打印配置文件统计信息的地方:
self.pr.disable()
s = io.StringIO()
sortby = SortKey.CUMULATIVE
ps = pstats.Stats(self.pr, stream=s).sort_stats(sortby)
ps.print_stats()
记得使用以下代码进行导入:
import cProfile, pstats, io
from pstats import SortKey
可以在 QGIS 中使用 line_profiler 而 运行 你的脚本。
您需要将它与其他导入一起导入到插件的主文件中,然后在主文件 class 之前添加 profile = line_profiler.LineProfiler()
,在主文件之前添加装饰器 @profile
函数进行分析,最后在函数的 return 之前添加 profile.print_stats(stream=stream)
。
我想还有其他方法可以做到,但这是我发现的方法对我来说足够好。
下面是处理插件的示例:
import os
import line_profiler
profile = line_profiler.LineProfiler()
class processingScriptExample(QgsProcessingAlgorithm):
INPUT_directory = 'INPUT_directory'
def initAlgorithm(self, config):
self.addParameter(QgsProcessingParameterNumber(self.INPUT_directory,
self.tr('Output directory'),
QgsProcessingParameterFile.Folder))
@profile
def processAlgorithm(self, parameters, context, feedback):
directory = self.parameterAsInt(parameters, self.INPUT_directory, context)
ls = []
for ii in range(1000000):
ls.append(ii)
ls = [ii for ii in range(1000000)]
path_profiling = os.path.join(directory, "line_profiling.txt")
with open(path_profiling, 'w') as stream:
profile.print_stats(stream=stream)
return {'Profiling file': path_profiling}
生成的文件:
Timer unit: 1e-07 s
Total time: 1.31260 s
File: C:\OSGeo4W\profiles\default/python/plugins\test\algo_test.py
Function: processAlgorithm at line 70
Line # Hits Time Per Hit % Time Line Contents
==============================================================
70 @profile
71 def processAlgorithm(self, parameters, context, feedback):
72 1 248.0 248.0 0.0 directory = self.parameterAsInt(parameters, self.INPUT_directory, context)
73
74 1 8.0 8.0 0.0 ls = []
75 1000001 5054594.0 5.1 38.5 for ii in range(1000000):
76 1000000 6633146.0 6.6 50.5 ls.append(ii)
77
78 1 1418416.0 1418416.0 10.8 ls = [ii for ii in range(1000000)]
79
80 1 561.0 561.0 0.0 path_profiling = os.path.join(directory, "line_profiling.txt")
81 1 19001.0 19001.0 0.1 with open(path_profiling, 'w') as stream:
82 profile.print_stats(stream=stream)
83
84 return {"Profiling file":path_profiling}