Slow Houdini launch

Has anyone found the houdini engine to really slow Houdini launch?
I’ve got a pretty vanilla config, and have cleared the studios standard PATH and PYTHONPATH environments, but when launching houdini from sg Desktop it’s taking 10x longer than launching houdini from the terminal.

My houdini_path only has the sg engine added to it, so there’s no studio config interfering as far as I can tell.

This is what I’m getting from the app_launch hook :

. PYTHONPATH :
‘/home/users/patrick/.shotgun/union/p412c773.basic.desktop/cfg/install/core/python:’
. HOUDINI_PATH :
‘/tmp/tk-houdini8kmK7q:/home/users/patrick/.shotgun/bundle_cache/app_store/tk-houdini/v1.6.1/classic_startup:&’
. app_path : /Volumes/software/houdini/hfs18.5.408/bin/houdini
. app_args :

Looking at my houdini log, I think this might help, you can see in the timestamps a 2 minute jump around this section :

2021-02-11 20:53:15,232 [121419 DEBUG sgtk.env.project.tk-houdini] Starting metrics dispatcher...
2021-02-11 20:53:15,233 [121419 DEBUG sgtk.core.util.shotgun.connection] Creating shotgun connection from <SessionUser patrick @ https://union.shotgunstudio.com>...
2021-02-11 20:53:15,233 [121419 DEBUG sgtk.env.project.tk-houdini] Added worker thread: <MetricsDispatchWorkerThread(Thread-2, started daemon 140419309852416)>
2021-02-11 20:53:15,234 [121419 DEBUG sgtk.stopwatch.tank.util.shotgun.connection] create_sg_connection: 0.000956s
2021-02-11 20:53:15,234 [121419 DEBUG sgtk.env.project.tk-houdini] Metrics dispatcher started.
2021-02-11 20:53:15,235 [121419 DEBUG sgtk.env.project.tk-houdini] Init complete: <Sgtk Engine 0x7fb60814af90: tk-houdini, env: project>
2021-02-11 20:55:17,941 [121419 DEBUG sgtk.env.project.tk-houdini] Grouped registered commands.
2021-02-11 20:55:17,942 [121419 DEBUG sgtk.env.project.tk-houdini] Collected context commands for dynamic menu.
2021-02-11 20:55:17,957 [121419 DEBUG sgtk.env.project.tk-houdini] Collected app commands for dynamic menu.
2021-02-11 20:56:37,786 [121419 DEBUG sgtk.env.project.tk-houdini.tk-multi-workfiles2] Synchronizing remote path cache...

Can you give any directions on how I can identify exactly what’s causing the slowdown?

Thanks
p.

1 Like

Argh,
I’ve made progress. Disabling the houdinig sg menu and shelf speeds up the load time, but then I’m left without Houdini.
I see in the engine code this issue is recognised in Windows, but there’s less indication that this is an issue under linux.
Basically, SG engine is waiting ages for the houdini GUI to load before finishing initialising… but for some reason, the houdini engine is delaying this far longer than would be the case without SG being loaded.
We’re on linux mint, cinamon desktop. Other than not loading any SG gui elements, and then rolling our own buttons, what can I do to speed things up?
Thanks
p.

Yeah I can confirm the Windows case (on Linux it seemed to be a lot better, at least).
There is also a long time of “Waiting for UI to become available…” which does not seem that much of an issue outside of Shotgun.

Yeah the registered commands line is really suspect here, or what came before it. Most likely commands are being fetched from the server/config. Also I see they are being written to xml, which is how Houdini reads them. Check out tk-houdini/python/tk_houdini/ui_generation.py

Would be awesome if someone would profile and identify the issue.

What version of Houdini is this?

Boo. I’m about to add this integration after updating our core, thinking things would be smooth sailing after that… I’ll let you know if I experience this and find anything.

yap, my experience is same houdini when it lunch is very slowly, how to make fast? site
best regards

There’s definitely something fishy going on.
I forked the tk-houdini engine to add some logging to see where the slowdown was happening, and it looks like it’s not during the engine initialisation phase at all anyway. All the gui setup is happens pretty quickly. Once that finishes, houdini hangs for around 4 minutes before loading.

Can anyone at SG help figure out what’s going on? Are there other SG methods being called during Houdini GUI initialisation that aren’t visible to us via the logs?
I’m really struggling to understand where the performance issue is coming from now.
Thanks!

1 Like

Ok, I finally figured this all out.
When bootstrapping tk-houdini, there are some pre-requisites that must be met :

  • TK_HOUDINI_TMP must be set
  • TK_HOUDINI_TMP path must be added to HOUDINI_PATH (is this not anywhere in the docs or code docstrings? )
  • you must set HOUDINI_NO_DEFAULT_SHELF_TOOLS=1 environment variable to prevent the minutes of delay when launching Houdini.

What I don’t understand is that it’s only when SG is bootstrapped that houdini builds a menu file in the temp location. This menu file creation is VERY slow. If you clear your houdinig temp dir, you’ll see the file slowly get generated with a tmp name : hfs113814-0.tmp

Why does this file only get generated when SG is bootstrapped?
If I set HOUDINI_NO_DEFAULT_SHELF_TOOLS=1, will that disable some SG features (eg the shogtun PDG nodes)?

The contents of this file is :

<?xml version="1.0" encoding="UTF-8"?>
<shelfDocument>
  <!-- This file contains definitions of shelves, toolbars, and tools.
 It should not be hand-edited when it is being used by the application.
 Note, that two definitions of the same element are not allowed in
 a single file. -->

  <tool name="shop_gen_geometry" label="Generic geometry" icon="SHOP_geometry">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_geometry</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Procedural</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_geometry')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_photon" label="Generic photon" icon="SHOP_photon">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_photon</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Photon</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_photon')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
    </keywordList>
  </tool>

  <tool name="shop_rsl_vopshaderclass" label="RSL Shader Class Builder" icon="SHOP_material">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/rsl_vopshaderclass</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Co-Shader</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'rsl_vopshaderclass')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_displace" label="Generic displace" icon="SHOP_displace">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_displace</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Displacement</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_displace')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_shadow" label="Generic shadow" icon="SHOP_shadow">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_shadow</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Light Shadow</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_shadow')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_surface" label="Generic surface" icon="SHOP_surface">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_surface</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Surface</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_surface')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_interior" label="Generic interior" icon="SHOP_fog">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_interior</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Interior</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_interior')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_light" label="Generic light" icon="SHOP_light">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_light</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Light</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_light')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_class" label="Generic class" icon="SHOP_material">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_class</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Co-Shader</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_class')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_fog" label="Generic fog" icon="SHOP_fog">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_fog</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Atmosphere</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_fog')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_coshader" label="Generic coshader" icon="SHOP_coshader">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_coshader</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Co-Shader</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_coshader')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_gen_image3d" label="Generic image3d" icon="SHOP_image3d">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_image3d</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Image 3D</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_image3d')]]></script>
  </tool>

  <tool name="shop_gen_generic" label="Generic generic" icon="SHOP_generic">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/gen_generic</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Generic</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'gen_generic')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="shop_rsl_vopstruct" label="RSL Struct Builder" icon="SHOP_material">
    <toolMenuContext name="viewer">
      <contextNetType>SHOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Shop/rsl_vopstruct</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <toolSubmenu>Co-Shader</toolSubmenu>
    <script scriptType="python"><![CDATA[import shoptoolutils

shoptoolutils.genericTool(kwargs, 'rsl_vopstruct')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="vop_CVEX_shader" label="CVEX Encapsulated Shader" icon="VOP_CVEX_shader">
    <toolMenuContext name="viewer">
      <contextNetType>VOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Vop/CVEX_shader</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <script scriptType="python"><![CDATA[import voptoolutils

voptoolutils.genericTool(kwargs, 'CVEX_shader')]]></script>
    <keywordList>
      <keyword>Mantra</keyword>
    </keywordList>
  </tool>

  <tool name="vop_buildarray" label="Build Array" icon="VOP_buildarray">
    <toolMenuContext name="viewer">
      <contextNetType>VOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Vop/buildarray</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <script scriptType="python"><![CDATA[import voptoolutils

voptoolutils.genericTool(kwargs, 'buildarray')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="vop_ris_RSLmaterial" label="RSL Material" icon="VOP_ris_RSLmaterial">
    <toolMenuContext name="viewer">
      <contextNetType>VOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Vop/ris_RSLmaterial</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <script scriptType="python"><![CDATA[import voptoolutils

voptoolutils.genericTool(kwargs, 'ris_RSLmaterial')]]></script>
    <keywordList>
      <keyword>RenderMan</keyword>
    </keywordList>
  </tool>

  <tool name="vop_for" label="For Loop" icon="VOP_for">
    <toolMenuContext name="viewer">
      <contextNetType>VOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Vop/for</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Digital Assets</toolSubmenu>
    <script scriptType="python"><![CDATA[import voptoolutils

voptoolutils.genericTool(kwargs, 'for')]]></script>
  </tool>

  <tool name="top_pdg_downloadfile" label="Download File" icon="TOP_downloadfile">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_downloadfile</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Files</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_downloadfile')]]></script>
  </tool>

  <tool name="top_pdg_partitionbyrange" label="Partition by Range" icon="TOP_partitionbyrange">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_partitionbyrange</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Partitioner</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_partitionbyrange')]]></script>
  </tool>

  <tool name="top_pdg_partitionbyattribute" label="Partition by Attribute" icon="TOP_partitionbyattribute">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_partitionbyattribute</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Partitioner</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_partitionbyattribute')]]></script>
  </tool>

  <tool name="top_pdg_renderifd" label="Render IFD" icon="TOP_renderifd">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_renderifd</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Render</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_renderifd')]]></script>
  </tool>

  <tool name="top_pdg_usdimportprimitives" label="USD Import Primitives" icon="TOP_usdimportprimitives">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_usdimportprimitives</contextOpType>
    </toolMenuContext>
    <toolSubmenu>USD</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_usdimportprimitives')]]></script>
  </tool>

  <tool name="top_pdg_shotgundownload" label="Download" icon="TOP_shotgundownload">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_shotgundownload</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Shotgun</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_shotgundownload')]]></script>
  </tool>

  <tool name="top_pdg_shotgunupload" label="Upload" icon="TOP_shotgunupload">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_shotgunupload</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Shotgun</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_shotgunupload')]]></script>
  </tool>

  <tool name="top_pdg_partitionbytile" label="Partition by Tile" icon="TOP_partitionbytile">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_partitionbytile</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Houdini</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_partitionbytile')]]></script>
  </tool>

  <tool name="top_pdg_ropfetch" label="Rop Fetch" icon="TOP_ropfetch">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_ropfetch</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Houdini</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_ropfetch')]]></script>
  </tool>

  <tool name="top_pdg_topfetchinput" label="Top Fetch Input" icon="TOP_topfetchinput">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_topfetchinput</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Houdini</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_topfetchinput')]]></script>
  </tool>

  <tool name="top_pdg_geometryimport" label="Geometry Import" icon="TOP_geometryimport">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_geometryimport</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Houdini</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_geometryimport')]]></script>
  </tool>

  <tool name="top_pdg_fileremove" label="File Remove" icon="TOP_fileremove">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_fileremove</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Files</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_fileremove')]]></script>
  </tool>

  <tool name="top_pdg_invoke" label="Invoke" icon="TOP_invoke">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_invoke</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Houdini</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_invoke')]]></script>
  </tool>

  <tool name="top_pdg_pythonscript" label="Python Script" icon="TOP_pythonscript">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_pythonscript</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Python</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_pythonscript')]]></script>
  </tool>

  <tool name="top_pdg_filterbyexpression" label="Filter by Expression" icon="TOP_filterbyexpression">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_filterbyexpression</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Utility</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_filterbyexpression')]]></script>
  </tool>

  <tool name="top_pdg_error" label="Error" icon="TOP_error">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_error</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Utility</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_error')]]></script>
  </tool>

  <tool name="top_pdg_partitionbynode" label="Partition by Node" icon="TOP_partitionbynode">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_partitionbynode</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Partitioner</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_partitionbynode')]]></script>
  </tool>

  <tool name="top_pdg_partitionbyframe" label="Partition by Frame" icon="TOP_partitionbyframe">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_partitionbyframe</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Partitioner</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_partitionbyframe')]]></script>
  </tool>

  <tool name="top_pdg_partitionbycombination" label="Partition by Combination" icon="TOP_partitionbycombination">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_partitionbycombination</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Partitioner</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

toptoolutils.genericTool(kwargs, 'pdg_partitionbycombination')]]></script>
  </tool>

  <tool name="top_pdg_wedge" label="Wedge" icon="TOP_wedge">
    <toolMenuContext name="viewer">
      <contextNetType>TOP</contextNetType>
    </toolMenuContext>
    <toolMenuContext name="network">
      <contextOpType>Top/pdg_wedge</contextOpType>
    </toolMenuContext>
    <toolSubmenu>Data</toolSubmenu>
    <script scriptType="python"><![CDATA[import toptoolutils

<truncated>

1 Like

I also noticed when loading a scene, I’m getting the following error.
Surely if we’re building the menus and saving them to the g_temp_env location, that we don’t want that location deleted when changing context?

[DEBUG tk-houdini] Destroying <Sgtk App 0x7f2c80c5c350: tk-multi-workfiles2, engine: <Sgtk Engine 0x7f2c80c9ee90: tk-houdini, env: project>>
[DEBUG tk-multi-workfiles2] Destroying tk-multi-workfiles2
[DEBUG tk-houdini] Destroying <Sgtk App 0x7f2c80d3a510: tk-multi-screeningroom, engine: <Sgtk Engine 0x7f2c80c9ee90: tk-houdini, env: project>>
[DEBUG tk-houdini] Destroying <Sgtk App 0x7f2c7e4655d0: tk-multi-shotgunpanel, engine: <Sgtk Engine 0x7f2c80c9ee90: tk-houdini, env: project>>
[DEBUG tk-multi-shotgunpanel] Destroying app...
[DEBUG tk-houdini] Destroying <Sgtk App 0x7f2c7e465c10: tk-multi-about, engine: <Sgtk Engine 0x7f2c80c9ee90: tk-houdini, env: project>>
[DEBUG tk-houdini] Destroying <Sgtk Engine 0x7f2c80c9ee90: tk-houdini, env: project>
[DEBUG tk-houdini] <Sgtk Engine 0x7f2c80c9ee90: tk-houdini, env: project>: Destroying...
[ERROR tk-houdini] Could not restart the engine!
Traceback (most recent call last):
  File "/Volumes/resources/release/tk-core/_release/v0.19.18/python/tank/platform/engine.py", line 3033, in _restart_engine
    engine.destroy()
  File "/Volumes/resources/release/tk-core/_release/v0.19.18/python/tank/platform/engine.py", line 718, in destroy
    self.destroy_engine()
  File "/Volumes/sandbox/patrick/git/shotgun/tk-houdini/engine.py", line 303, in destroy_engine
    shutil.rmtree(os.environ[bootstrap.g_temp_env])
  File "/Volumes/software/houdini/hfs18.5.408/python/lib/python2.7/shutil.py", line 270, in rmtree
    onerror(os.rmdir, path, sys.exc_info())
  File "/Volumes/software/houdini/hfs18.5.408/python/lib/python2.7/shutil.py", line 268, in rmtree
    os.rmdir(path)
OSError: [Errno 1] Operation not permitted: '/tmp/houdini_temp'
[INFO tk-houdini] Toolkit platform was restarted.
2 Likes

Excellent dive Patrick, thanks for that! So it was the menu xml generation :slight_smile:

Edit: from a cursory scan of the file, it seems not to change between context etc? This means the fix in the engine should be relatively simple - just do not regenerate the file every time if it exists.

The menu file generation is a houdini thing as far as I can tell.

SG menu generation is FAST… it’s houdini that does a slow menu generation for some reason.

The env var I mentioned disables this feature… but I’m unsure if it means we lose essential functionality.

I’m not sure how we can tell houdini to re-use an existing menu file, or to speed up that process.
I think I might log this as a houdini bug, but it would probably be best if SG developers do the talking… it’s unclear where the failure lies; it only happens when we add SG menus, but it seems to be houdini code that’s inefficient.

Yeah, Houdini’s public API docs for menus seems to point people to try setup “static” menus beforehand in a XML document on $HOUDINI_MENU_PATH

I did a quick test to try dive into the sub-QWiget to see if there are any QMenuBar underneath hou.qt.mainWindow() to see if we can add actions directly (assuming it will be faster), to no avail:

Python script for Houdini 18.5
import hou
from hutil.Qt import QtWidgets

def recurse_children(widget, max_depth=4, _indent=0):
    print("%s%s %s" % ("|  " * _indent, widget.objectName(), widget))
    for child in widget.children():
        if isinstance(child, QtWidgets.QWidget):
            recurse_children(child, max_depth=max_depth-1, _indent=_indent+1)
    

recurse_children(hou.qt.mainWindow())
RE_Window <PySide2.QtWidgets.QWidget object at 0x7f466f8b1878>
|  RE_GLDrawableWrapper <PySide2.QtWidgets.QWidget object at 0x7f466f9b4f38>
|  |  RE_GLDrawable <PySide2.QtWidgets.QWidget object at 0x7f466f92c4d0>
|  |  |  RE_Window <PySide2.QtWidgets.QWidget object at 0x7f466f92c0e0>
|  |  |  |  RE_GLDrawableWrapper <PySide2.QtWidgets.QWidget object at 0x7f466f9b3a70>
|  |  |  |  |  RE_GLDrawable <PySide2.QtWidgets.QWidget object at 0x7f466f9b3ab8>
|  |  |  RE_Window <PySide2.QtWidgets.QWidget object at 0x7f466f98d950>
|  |  |  |  RE_GLDrawableWrapper <PySide2.QtWidgets.QWidget object at 0x7f466f9b3908>
|  |  |  |  |  RE_GLDrawable <PySide2.QtWidgets.QWidget object at 0x7f466f9b3f38>
|  |  |  RE_Window <PySide2.QtWidgets.QWidget object at 0x7f466f98da28>
|  |  |  |  RE_GLDrawableWrapper <PySide2.QtWidgets.QWidget object at 0x7f466f9b3a70>
|  |  |  |  |  RE_GLDrawable <PySide2.QtWidgets.QWidget object at 0x7f466f9b3ab8>
|  |  |  |  |  |  RE_Window <PySide2.QtWidgets.QWidget object at 0x7f466f9b3cf8>
|  |  |  |  |  |  |  RE_GLDrawableWrapper <PySide2.QtWidgets.QWidget object at 0x7f466f94f2d8>
|  |  |  |  |  |  |  |  RE_GLDrawable <PySide2.QtWidgets.QWidget object at 0x7f466f94fc68>
|  |  |  |  |  |  RE_Window <PySide2.QtWidgets.QWidget object at 0x7f466f9b3c68>
|  |  |  |  |  |  |  RE_GLDrawableWrapper <PySide2.QtWidgets.QWidget object at 0x7f466f94f248>
|  |  |  |  |  |  |  |  RE_GLDrawable <PySide2.QtWidgets.QWidget object at 0x7f466f94fe18>

Maybe it might worth sending off a “scripting” request to SideFX to see if there is a way to directly access and modify the main menu bar in Python so Shogun can build it’s dynamic menus without having to setup a temporary XML file on every context change

1 Like

Instead of using XML, you could create a python panel on Houdini startup, move the panel to a desired location, and hook the QMenuBar there

Hi all

SideFX did some digging and turned up the following unmerged pull request in tk-houdini:

I’ve applied this to a clone of tk-houdini v1.8.1 and it solves the long startup issue.

Regards
David

1 Like