260 lines
11 KiB
HTML
260 lines
11 KiB
HTML
<html><head><title>Macro Recompute Profiler/it</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><link type='text/css' href='wiki.css' rel='stylesheet'></head><body><h1>Macro Recompute Profiler/it</h1></div>
|
|
|
|
<div id="mw-content-text" lang="it" dir="ltr" class="mw-content-ltr"><hr/><div class="mw-parser-output"><table class="fcinfobox wikitable ct" width="100%" style="float: right; width: 230px; margin-left: 10px;">
|
|
<tr>
|
|
<td class="ctTitle">
|
|
<h3><span class="mw-headline" id="Macro_Recompute_Profiler"><a href="https://www.freecadweb.org/wiki/index.php?title=File:Text-x-python.png" class="image"><img alt="Text-x-python.png" src="32px-Text-x-python.png" width="32" height="32" srcset="/wiki/images/2/2c/Text-x-python.png 1.5x" /></a> Macro Recompute Profiler</span></h3>
|
|
</td></tr>
|
|
<tr>
|
|
<th class="ctOdd">Descrizione
|
|
</th></tr>
|
|
<tr>
|
|
<td class="ctEven left">Misura il tempo necessario per ricalcolare ogni funzione del progetto
|
|
</td></tr>
|
|
<tr>
|
|
<th class="ctOdd">Autore
|
|
</th></tr>
|
|
<tr>
|
|
<td class="ctEven"><a href="https://www.freecadweb.org/wiki/index.php?title=User:DeepSOIC" title="User:DeepSOIC">DeepSOIC</a>
|
|
</td></tr>
|
|
<tr>
|
|
<th class="ctOdd">Link
|
|
</th></tr>
|
|
<tr>
|
|
<td class="ctEven"><a href="https://www.freecadweb.org/wiki/index.php?title=Macros_recipes/it" title="Macros recipes/it">Esempi di macro</a><br /><a href="https://www.freecadweb.org/wiki/index.php?title=How_to_install_macros/it" title="How to install macros/it">Come installare le Macro</a><br /><a href="https://www.freecadweb.org/wiki/index.php?title=Customize_Toolbars/it" title="Customize Toolbars/it">Personalizzare la barra degli strumenti</a>
|
|
</td></tr>
|
|
<tr>
|
|
<th class="ctOdd">Versione
|
|
</th></tr>
|
|
<tr>
|
|
<td class="ctEven macro-version">0.1
|
|
</td></tr>
|
|
<tr>
|
|
<th class="ctOdd">Data ultima modifica
|
|
</th></tr>
|
|
<tr>
|
|
<td class="ctEven macro-date">2017-04-03
|
|
</td></tr>
|
|
<tr>
|
|
<th class="ctOdd">
|
|
</th></tr>
|
|
<tr>
|
|
<td class="ctToc"><br /><div id="toc" class="toc"><div class="toctitle"><h2>Contents</h2></div>
|
|
<ul>
|
|
<li class="toclevel-1"><a href="#Macro_Recompute_Profiler"><span class="tocnumber">1</span> <span class="toctext">Macro Recompute Profiler</span></a></li>
|
|
<li class="toclevel-1 tocsection-1"><a href="#Descrizione"><span class="tocnumber">2</span> <span class="toctext">Descrizione</span></a></li>
|
|
<li class="toclevel-1 tocsection-2"><a href="#Uso"><span class="tocnumber">3</span> <span class="toctext">Uso</span></a></li>
|
|
<li class="toclevel-1 tocsection-3"><a href="#Post-processing_dei_resultati"><span class="tocnumber">4</span> <span class="toctext">Post-processing dei resultati</span></a></li>
|
|
<li class="toclevel-1 tocsection-4"><a href="#Macro"><span class="tocnumber">5</span> <span class="toctext">Macro</span></a></li>
|
|
<li class="toclevel-1 tocsection-5"><a href="#Versione_di_FreeCAD"><span class="tocnumber">6</span> <span class="toctext">Versione di FreeCAD</span></a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
</td></tr>
|
|
</table>
|
|
<p><br />
|
|
</p>
|
|
<h2><span class="mw-headline" id="Descrizione">Descrizione</span></h2>
|
|
<p>Questa macro serve per trovare quali sono le funzioni che causano lunghi ritardi negli aggiornamenti del progetto. Essa esegue un ricalcolo, misurando il tempo necessario per ricalcolare ogni funzione.
|
|
</p>
|
|
<h2><span class="mw-headline" id="Uso">Uso</span></h2>
|
|
<p>Questa macro richiede almeno la versione 0.17.10644 di FreeCAD
|
|
</p><p>Salvare la macro in un file.
|
|
</p><p>1. Aprire il progetto
|
|
</p><p>2. Fare clic destro su un oggetto nella struttura ad albero del modello, selezionare "Marca da ricalcolare"
|
|
</p><p>3. Avviare questa macro.
|
|
</p><p>Appare una barra di avanzamento. Man mano che ogni oggetto viene ricalcolato, viene stampata una riga nel pannello Report, che contiene il tempo e l'etichetta dell'oggetto. Se FreeCAD non riesce a ricalcolare un oggetto, la macro visualizza un messaggio di errore e termina il processo.
|
|
</p>
|
|
<h2><span class="mw-headline" id="Post-processing_dei_resultati">Post-processing dei resultati</span></h2>
|
|
<p>I messagi della macro sono intercalati con i messaggi generali prodotti dal ricalcolo delle caratteristiche. Generalmente appare qualcosa di simile:
|
|
</p>
|
|
<pre>Recomputing... (time in seconds, label)
|
|
Sketcher::setUpSketch()-T:0
|
|
Sketcher::Solve()-DogLeg-T:0
|
|
0.00999999046326Sketch - master section
|
|
0.0199999809265Clone of Sketch - master section (2D)001
|
|
Sketcher::setUpSketch()-T:0
|
|
Sketcher::Solve()-DogLeg-T:0
|
|
0.00999999046326Sketch013
|
|
Sketcher::setUpSketch()-T:0
|
|
Sketcher::Solve()-DogLeg-T:0
|
|
0.00999999046326Sketch011
|
|
0.0Clone of Sketch - master section (2D)
|
|
Sketcher::setUpSketch()-T:0
|
|
Sketcher::Solve()-DogLeg-T:0
|
|
0.0Sketch008
|
|
0.130000114441LinearArray
|
|
Sketcher::setUpSketch()-T:0
|
|
Sketcher::Solve()-DogLeg-T:0
|
|
... </pre>
|
|
<p>Le righe dei risultati hanno una firma che consente di estrarle: iniziano con una tabella. Quindi, se si copia-incolla la parte intera in un foglio di calcolo, i messaggi generici finiscono nella colonna 1, mentre i risultati finiscono nelle colonne 2 e 3. Perciò, è possibile ordinarli in 2 colonne per ottenere un bella tabella di questo tipo:
|
|
</p>
|
|
<pre>0.59100008Slice
|
|
0.352999926Populate LinearArray with Compound
|
|
0.160000086CompoundFilter
|
|
0.138999939Cut
|
|
0.130000114LinearArray
|
|
0.108999968Fusion
|
|
0.069999933Moved CompoundFilter
|
|
0.067000151Module - spokes
|
|
0.029999971Sweep
|
|
0.019999981Clone of Sketch - master section (2D)001
|
|
0.010999918ArrayFilter003
|
|
... </pre>
|
|
<p>(Per MS-Excel, facendo copia-incolla del testo dal rapporto non lo divide in colonne, non so perché ... incollando il testo in Notepad e ri-copiandolo poi da Notepad funziona meglio.)
|
|
</p>
|
|
<h2><span class="mw-headline" id="Macro">Macro</span></h2>
|
|
<p><b>RecomputeProfiler.FCMacro</b>
|
|
</p>
|
|
<pre>__Title__="Macro Recompute Profiler"
|
|
__Author__ = "DeepSOIC"
|
|
__Version__ = "0.1"
|
|
__Date__ = "03.04.2017"
|
|
|
|
__Comment__ = "Measures time it takes to recmpute features in a project"
|
|
__Wiki__ = "https://www.freecadweb.org/wiki/index.php?title=Macro_Recompute_Profiler"
|
|
__Help__ = "Right-click an object, and pick 'Mark to recompute', then run this macro. This will only profile recomputing the subgraph. To profile the whole project, right-click the project in tree view, and pick 'Mark to recompute', then run this macro. Results will be printed to report view."
|
|
__Status__ = "experimental"
|
|
__Requires__ = "freecad 0.17.10644"
|
|
__Communication__ = "https://forum.freecadweb.org/memberlist.php?mode=viewprofile&u=3888"
|
|
|
|
import FreeCAD as App
|
|
|
|
import FreeCADGui as Gui
|
|
|
|
class ExecutionError(Exception):
|
|
pass
|
|
|
|
class CancelError(Exception):
|
|
pass
|
|
|
|
def execute(feature):
|
|
feature.recompute()
|
|
if 'Invalid' in feature.State:
|
|
raise ExecutionError("Feature '{label}' failed to recompute".format(label= feature.Label))
|
|
|
|
def msgbox(title, text):
|
|
from PySide import QtGui
|
|
mb = QtGui.QMessageBox()
|
|
mb.setIcon(mb.Icon.Information)
|
|
mb.setText(text)
|
|
mb.setWindowTitle(title)
|
|
mb.exec_()
|
|
|
|
def log(string):
|
|
App.Console.PrintWarning(string+"\n")
|
|
|
|
def getAllDependent(feat_list):
|
|
'''getAllDependent(feat_list): gets all features that depend on features in feat_list, directly or indirectly.
|
|
Returns a set. Features from feat_list are not included, unless there are interdependencies between them.'''
|
|
|
|
list_traversing_now = feat_list
|
|
set_of_deps = set()
|
|
list_of_deps = []
|
|
|
|
while len(list_traversing_now) > 0:
|
|
list_to_be_traversed_next = []
|
|
for feat in list_traversing_now:
|
|
for dep in feat.InList:
|
|
if not (dep in set_of_deps):
|
|
set_of_deps.add(dep)
|
|
list_of_deps.append(dep)
|
|
list_to_be_traversed_next.append(dep)
|
|
|
|
list_traversing_now = list_to_be_traversed_next
|
|
|
|
return set_of_deps
|
|
|
|
|
|
def run():
|
|
touched = [obj for obj in App.ActiveDocument.Objects if 'Touched' in obj.State]
|
|
|
|
if len(touched) == 0:
|
|
App.ActiveDocument.RecomputesFrozen = True
|
|
msgbox("Macro Recompute Profiler", "Project was switched to suspend recomputes. Please modify an object that triggers a recompute, and run this macro again. The macro will perform a step-by-step recompute, and measure the time it takes to recompute features.")
|
|
return
|
|
|
|
log("{n} features are touched".format(n= len(touched)))
|
|
|
|
log("Generating execution order...")
|
|
|
|
to_be_executed = set.union(getAllDependent(touched), set(touched))
|
|
log("Number of features to execute: {n}".format(n= len(to_be_executed)))
|
|
|
|
exec_list = []
|
|
for obj in App.ActiveDocument.TopologicalSortedObjects[::-1]:
|
|
if obj in to_be_executed:
|
|
exec_list.append(obj)
|
|
assert(len(exec_list) == len(to_be_executed))
|
|
n = len(exec_list)
|
|
|
|
log("Execution order:")
|
|
for obj in exec_list:
|
|
log(" "+obj.Label)
|
|
|
|
|
|
import PySide
|
|
progress = PySide.QtGui.QProgressDialog(u"Preparing to recompute....", u"Abort", 0, n+1)
|
|
progress.setModal(True)
|
|
progress.show()
|
|
|
|
try:
|
|
log("Recomputing... (time in seconds, label)")
|
|
import time
|
|
for obj in exec_list:
|
|
progress.setValue(progress.value()+1)
|
|
progress.setLabelText("Recomputing {feature}...".format(feature= obj.Label))
|
|
if progress.wasCanceled():
|
|
raise CancelError()
|
|
|
|
time_start = time.time()
|
|
try:
|
|
execute(obj)
|
|
finally:
|
|
exec_time = time.time()-time_start
|
|
log("\t{time}\t{label}".format(time= exec_time, label= obj.Label))
|
|
|
|
progress.setValue(n+1)
|
|
msgbox("Macro Recompute Profiler", "Recompute completed. Results are in report view.")
|
|
|
|
for obj in exec_list:
|
|
obj.purgeTouched()
|
|
|
|
except Exception as err:
|
|
msgbox("Macro Recompute Profiler", "An error occured: {err}".format(err= str(err)))
|
|
finally:
|
|
progress.hide()
|
|
App.ActiveDocument.RecomputesFrozen = False
|
|
|
|
run() </pre>
|
|
<h2><span class="mw-headline" id="Versione_di_FreeCAD">Versione di FreeCAD</span></h2>
|
|
<p>Questa macro richiede una versione di FreeCAD non inferiore alla 0.17.10644, che è la versione in cui è stato reso disponibile App.ActiveDocument.RecomputesFrozen. Potrebbe essere funzionare anche con una vesrsione di FreeCAD un po' più vecchia, ma certamente non funziona con v0.16.
|
|
</p><p>Questa macro è stata creata usando questa versione di FreeCAD:
|
|
</p>
|
|
<pre>OS: Windows 10
|
|
Word size of OS: 64-bit
|
|
Word size of FreeCAD: 64-bit
|
|
Version: 0.17.10665 (Git)
|
|
Build type: Release
|
|
Branch: master
|
|
Hash: 47847513a85ff6615774ef628230f79e37471daf
|
|
Python version: 2.7.8
|
|
Qt version: 4.8.7
|
|
Coin version: 4.0.0a
|
|
OCC version: 7.0.0 </pre>
|
|
<div style="clear:both"></div>
|
|
</div>
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div><div class="printfooter">
|
|
Online version: "<a dir="ltr" href="https://www.freecadweb.org/wiki/index.php?title=Macro_Recompute_Profiler/it&oldid=245022">http://www.freecadweb.org/wiki/index.php?title=Macro_Recompute_Profiler/it&oldid=245022</a>"</div>
|
|
<div id="catlinks" class="catlinks" data-mw="interface"></div><div class="visualClear"></div>
|
|
</div>
|
|
</div>
|
|
<div id="mw-navigation">
|
|
<h2>Navigation menu</h2>
|
|
|
|
</body></html> |