Re: Dispatch vs EnsureDispatch performance
Sven Bardos via python-win32 <[email protected]> Wed, 17 Jul 2024 11:30:42 +0200
| Newsgroups | gmane.comp.python.windows |
|---|---|
| Message-ID | <CAP10ovyvggv-ecB6AWc7KCg+_Vvxfo3n_QtWDgF=_v-UMAaTeA@mail.gmail.com> |
--===============7062537591709426669==
Content-Type: multipart/alternative; boundary="0000000000005c43b5061d6e1e5d"
--0000000000005c43b5061d6e1e5d
Content-Type: text/plain; charset="UTF-8"
Hi Mark,
I found some time to debug and profile my issue a little bit more.
In my scenario I call a COM method which returns a list of 14195 integers
plus the amount of the found objects.
If I profile that call I get the following:
ncalls tottime percall cumtime percall filename:lineno(function)
...
1 0.000 0.000 0.025 0.025 __init__.py:572(_ApplyTypes_)
1 0.000 0.000 0.007 0.007 __init__.py:603(_get_good_object_)
14195 0.001 0.000 0.001 0.000
__init__.py:608(_get_good_single_object_)
14198/1 0.005 0.000 0.007 0.007
__init__.py:614(_get_good_object_)
...
So _get_good_object_ is called ~14200 times.
If I do that in a loop 100x, I get an execution time of ~3.3s
If I change the code in the _ApplyTypes_ function to:
def _ApplyTypes_(self, dispid, wFlags, retType, argTypes, user,
resultCLSID, *args):
return self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType,
argTypes, *args)
# return self._get_good_object_(
# self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType,
argTypes, *args),
# user,
# resultCLSID,
# )
that is, avoiding the _get_good_object_() calls, the execution time is
~1.6s for 100 iterations. Which is ~50% of the original time. The result is
the same, in this case.
Do you have any thoughts on this?
Best regards,
Sven
Am Mi., 17. Apr. 2024 um 17:19 Uhr schrieb Mark Hammond <
[email protected]>:
> I'm mildly surprised by that - a profiler might show some low-hanging
> fruit, and/or might show different characteristics when many more functions
> are used. However, the primary reason for EnsureDispatch is for better
> support of the object model - there's far more context available and this
> less chance of upsetting some COM objects - eg, when `foo.bar` is seen,
> EnsureDispatch knows for sure that `bar` is a method, but dynamic dispatch
> doesn't know if the resulting object is going to be called or not.
>
> HTH,
>
> Mark
> On 2024-04-17 2:07 a.m., Sven Bardos via python-win32 wrote:
>
> Hi,
>
> shouldn't be EnsureDispatch be faster than Dispatch once the code
> generation is done?
>
> I've measured it by calling 6000 COM calls like this:
>
> dirpath = Path('C:/Users/sbardos/AppData/Local/Temp/gen_py/3.10/')
> if dirpath.exists() and dirpath.is_dir():
> shutil.rmtree(dirpath)
>
> app = Dispatch("CT.Application")
> job = app.CreateJobObject()
>
> start = timer()
>
> for i in range(2000):
> cnt, devIds = job.GetAllDeviceIds()
> cnt, sheetIds = job.GetSheetIds()
> dev = job.CreateDeviceObject()
>
> end = timer()
> print(f"Time ellapsed (late): {end - start}s")
> and the ensure Dispatch version:
> app = EnsureDispatch("CT.Application")
> job = app.CreateJobObject()
> start = timer()
> for i in range(2000):
> cnt, devIds = job.GetAllDeviceIds(None)
> cnt, sheetIds = job.GetSheetIds(None)
> dev = job.CreateDeviceObject()
> end = timer()
> print(f"Time ellapsed (early): {end - start}s")
> EnsureDispatch is a little bit slower ~4.2s compared to ~4.0s.
> If I don't get a performance boost with EnsureDispatch, is there even a
> point using it?
>
> Thanks,
> Sven
>
> _______________________________________________
> python-win32 mailing [email protected]://mail.python.org/mailman/listinfo/python-win32
>
>
--0000000000005c43b5061d6e1e5d
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div dir=3D"ltr">Hi Mark,<div><br><div>I found some time t=
o debug and profile my issue a little bit more.</div></div><div>In my scena=
rio I call a COM method which returns a list of 14195 integers plus the amo=
unt of the found objects.</div><div><br></div><div>If I profile that call I=
get the following:</div><div><br></div><div><font face=3D"garamond, times =
new roman, serif">ncalls =C2=A0tottime =C2=A0percall =C2=A0cumtime =C2=A0pe=
rcall filename:lineno(function)<br></font></div><div><font face=3D"garamond=
, times new roman, serif">...</font></div><div><font face=3D"garamond, time=
s new roman, serif">1 =C2=A0 =C2=A00.000 =C2=A0 =C2=A00.000 =C2=A0 =C2=A00.=
025 =C2=A0 =C2=A00.025 __init__.py:572(_ApplyTypes_)<br>1 =C2=A0 =C2=A00.00=
0 =C2=A0 =C2=A00.000 =C2=A0 =C2=A00.007 =C2=A0 =C2=A00.007 __init__.py:603(=
_get_good_object_)<br>14195 =C2=A0 =C2=A00.001 =C2=A0 =C2=A00.000 =C2=A0 =
=C2=A00.001 =C2=A0 =C2=A00.000 __init__.py:608(_get_good_single_object_)<br=
>14198/1 =C2=A0 =C2=A00.005 =C2=A0 =C2=A00.000 =C2=A0 =C2=A00.007 =C2=A0 =
=C2=A00.007 __init__.py:614(_get_good_object_)<br></font></div><div>...</di=
v><div><br></div><div>So _get_good_object_ is called ~14200 times.</div><di=
v>If I do that in a loop 100x, I get an execution time of ~3.3s</div><div><=
br></div><div>If I change the code in the <font face=3D"garamond, times new=
roman, serif">_ApplyTypes_ </font>function to:</div><div><br></div><div st=
yle=3D"color:rgb(204,204,204);background-color:rgb(31,31,31);font-family:Co=
nsolas,"Courier New",monospace;font-size:14px;line-height:19px;wh=
ite-space:pre"><div>=C2=A0 =C2=A0 <span style=3D"color:rgb(86,156,214)">def=
</span> <span style=3D"color:rgb(220,220,170)">_ApplyTypes_</span>(<span st=
yle=3D"color:rgb(156,220,254)">self</span>, <span style=3D"color:rgb(156,22=
0,254)">dispid</span>, <span style=3D"color:rgb(156,220,254)">wFlags</span>=
, <span style=3D"color:rgb(156,220,254)">retType</span>, <span style=3D"col=
or:rgb(156,220,254)">argTypes</span>, <span style=3D"color:rgb(156,220,254)=
">user</span>, <span style=3D"color:rgb(156,220,254)">resultCLSID</span>, <=
span style=3D"color:rgb(212,212,212)">*</span><span style=3D"color:rgb(156,=
220,254)">args</span>):</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <span style=
=3D"color:rgb(197,134,192)">return</span> <span style=3D"color:rgb(156,220,=
254)">self</span>._oleobj_.InvokeTypes(<span style=3D"color:rgb(156,220,254=
)">dispid</span>, <span style=3D"color:rgb(181,206,168)">0</span>, <span st=
yle=3D"color:rgb(156,220,254)">wFlags</span>, <span style=3D"color:rgb(156,=
220,254)">retType</span>, <span style=3D"color:rgb(156,220,254)">argTypes</=
span>, <span style=3D"color:rgb(212,212,212)">*</span><span style=3D"color:=
rgb(156,220,254)">args</span>)</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <span =
style=3D"color:rgb(106,153,85)"># return self._get_good_object_(</span></di=
v><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <span style=3D"color:rgb(106,153,85)"># =
=C2=A0 =C2=A0 self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argType=
s, *args),</span></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <span style=3D"colo=
r:rgb(106,153,85)"># =C2=A0 =C2=A0 user,</span></div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 <span style=3D"color:rgb(106,153,85)"># =C2=A0 =C2=A0 resultCLSI=
D,</span></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 <span style=3D"color:rgb(10=
6,153,85)"># )</span></div></div><div><br></div><div>that is, avoiding the =
_get_good_object_() calls, the execution time is ~1.6s for 100 iterations. =
Which is ~50% of the original time. The result is the same, in this case.</=
div><div><br></div><div>Do you have any thoughts on this?</div><div><br></d=
iv><div>Best regards,</div><div>Sven</div><div>=C2=A0</div></div><br><div c=
lass=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">Am Mi., 17. Apr.=
2024 um 17:19=C2=A0Uhr schrieb Mark Hammond <<a href=3D"mailto:skippy.h=
[email protected]">[email protected]</a>>:<br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid=
rgb(204,204,204);padding-left:1ex"><u></u>
=20
=20
=20
<div>
<p>I'm mildly surprised by that - a profiler might show some
low-hanging fruit, and/or might show different characteristics
when many more functions are used. However, the primary reason for
EnsureDispatch is for better support of the object model - there'=
s
far more context available and this less chance of upsetting some
COM objects - eg, when `foo.bar` is seen, EnsureDispatch knows for
sure that `bar` is a method, but dynamic dispatch doesn't know if
the resulting object is going to be called or not.</p>
<p>HTH,</p>
<p>Mark<br>
</p>
<div>On 2024-04-17 2:07 a.m., Sven Bardos
via python-win32 wrote:<br>
</div>
<blockquote type=3D"cite">
=20
<div dir=3D"ltr">Hi,
<div><br>
<div>shouldn't be EnsureDispatch be faster than Dispatch once
the code generation is done?</div>
<div><br>
</div>
<div>I've measured it by calling 6000 COM calls like this:</d=
iv>
<div><br>
</div>
<div>
<div style=3D"color:rgb(204,204,204);background-color:rgb(31,31=
,31);font-family:Consolas,"Courier New",monospace;font-size:14px;=
line-height:19px;white-space:pre-wrap"><div><span style=3D"color:rgb(156,22=
0,254)">dirpath</span> <span style=3D"color:rgb(212,212,212)">=3D</span> <s=
pan style=3D"color:rgb(78,201,176)">Path</span>(<span style=3D"color:rgb(20=
6,145,120)">'C:/Users/sbardos/AppData/Local/Temp/gen_py/3.10/'</spa=
n>)</div><div><span style=3D"color:rgb(197,134,192)">if</span> <span style=
=3D"color:rgb(156,220,254)">dirpath</span>.<span style=3D"color:rgb(220,220=
,170)">exists</span>() <span style=3D"color:rgb(86,156,214)">and</span> <sp=
an style=3D"color:rgb(156,220,254)">dirpath</span>.<span style=3D"color:rgb=
(220,220,170)">is_dir</span>():</div><div>=C2=A0 =C2=A0 <span style=3D"colo=
r:rgb(78,201,176)">shutil</span>.<span style=3D"color:rgb(156,220,254)">rmt=
ree</span>(<span style=3D"color:rgb(156,220,254)">dirpath</span>)</div></di=
v>
</div>
<div><br>
</div>
<div>
<div style=3D"line-height:19px">
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)"><span style=3D"color:rgb(156,220,254)">app</span> <=
span style=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb(2=
20,220,170)">Dispatch</span>(<span style=3D"color:rgb(206,145,120)">"C=
T.Application"</span>)</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)"><span style=3D"color:rgb(156,220,254)">job</span> <=
span style=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb(1=
56,220,254)">app</span>.CreateJobObject()</div>
<br>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)"><span style=3D"color:rgb(156,220,254)">start</span>=
<span style=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb=
(156,220,254)">timer</span>()</div>
<br>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)"><span style=3D"color:rgb(197,134,192)">for</span> <=
span style=3D"color:rgb(156,220,254)">i</span> <span style=3D"color:rgb(197=
,134,192)">in</span> <span style=3D"color:rgb(78,201,176)">range</span>(<sp=
an style=3D"color:rgb(181,206,168)">2000</span>):</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)">=C2=A0 =C2=A0 <span style=3D"color:rgb(156,220,254)=
">cnt</span>, <span style=3D"color:rgb(156,220,254)">devIds</span> <span st=
yle=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb(156,220,=
254)">job</span>.GetAllDeviceIds()</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)">=C2=A0 =C2=A0 <span style=3D"color:rgb(156,220,254)=
">cnt</span>, <span style=3D"color:rgb(156,220,254)">sheetIds</span> <span =
style=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb(156,22=
0,254)">job</span>.GetSheetIds()</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)">=C2=A0 =C2=A0 <span style=3D"color:rgb(156,220,254)=
">dev</span> <span style=3D"color:rgb(212,212,212)">=3D</span> <span style=
=3D"color:rgb(156,220,254)">job</span>.CreateDeviceObject()</div>
<br>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)"><span style=3D"color:rgb(156,220,254)">end</span> <=
span style=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb(1=
56,220,254)">timer</span>()</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)"><span style=3D"color:rgb(220,220,170)">print</span>=
(<span style=3D"color:rgb(86,156,214)">f</span><span style=3D"color:rgb(206=
,145,120)">"Time ellapsed (late): </span><span style=3D"color:rgb(86,1=
56,214)">{</span><span style=3D"color:rgb(156,220,254)">end</span> <span st=
yle=3D"color:rgb(212,212,212)">-</span> <span style=3D"color:rgb(156,220,25=
4)">start</span><span style=3D"color:rgb(86,156,214)">}</span><span style=
=3D"color:rgb(206,145,120)">s"</span>)</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)">
</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)">and the ensure Dispatch version:</div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&qu=
ot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgrou=
nd-color:rgb(31,31,31)">
</div>
<div>
<div style=3D"color:rgb(204,204,204);font-family:Consolas,&=
quot;Courier New",monospace;font-size:14px;white-space:pre-wrap;backgr=
ound-color:rgb(31,31,31);line-height:19px"><div><span style=3D"color:rgb(15=
6,220,254)">app</span> <span style=3D"color:rgb(212,212,212)">=3D</span> <s=
pan style=3D"color:rgb(220,220,170)">EnsureDispatch</span>(<span style=3D"c=
olor:rgb(206,145,120)">"CT.Application"</span>)</div><div><span s=
tyle=3D"color:rgb(156,220,254)">job</span> <span style=3D"color:rgb(212,212=
,212)">=3D</span> <span style=3D"color:rgb(156,220,254)">app</span>.CreateJ=
obObject()</div>
<div><span style=3D"color:rgb(156,220,254)">start</span> <span style=3D"col=
or:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb(156,220,254)">time=
r</span>()</div>
<div><span style=3D"color:rgb(197,134,192)">for</span> <span style=3D"color=
:rgb(156,220,254)">i</span> <span style=3D"color:rgb(197,134,192)">in</span=
> <span style=3D"color:rgb(78,201,176)">range</span>(<span style=3D"color:r=
gb(181,206,168)">2000</span>):</div><div>=C2=A0 =C2=A0 <span style=3D"color=
:rgb(156,220,254)">cnt</span>, <span style=3D"color:rgb(156,220,254)">devId=
s</span> <span style=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"c=
olor:rgb(156,220,254)">job</span>.GetAllDeviceIds(<span style=3D"color:rgb(=
86,156,214)">None</span>)</div><div>=C2=A0 =C2=A0 <span style=3D"color:rgb(=
156,220,254)">cnt</span>, <span style=3D"color:rgb(156,220,254)">sheetIds</=
span> <span style=3D"color:rgb(212,212,212)">=3D</span> <span style=3D"colo=
r:rgb(156,220,254)">job</span>.GetSheetIds(<span style=3D"color:rgb(86,156,=
214)">None</span>)</div><div>=C2=A0 =C2=A0 <span style=3D"color:rgb(156,220=
,254)">dev</span> <span style=3D"color:rgb(212,212,212)">=3D</span> <span s=
tyle=3D"color:rgb(156,220,254)">job</span>.CreateDeviceObject()</div>
<div><span style=3D"color:rgb(156,220,254)">end</span> <span style=3D"color=
:rgb(212,212,212)">=3D</span> <span style=3D"color:rgb(156,220,254)">timer<=
/span>()</div><div><span style=3D"color:rgb(220,220,170)">print</span>(<spa=
n style=3D"color:rgb(86,156,214)">f</span><span style=3D"color:rgb(206,145,=
120)">"Time ellapsed (early): </span><span style=3D"color:rgb(86,156,2=
14)">{</span><span style=3D"color:rgb(156,220,254)">end</span> <span style=
=3D"color:rgb(212,212,212)">-</span> <span style=3D"color:rgb(156,220,254)"=
>start</span><span style=3D"color:rgb(86,156,214)">}</span><span style=3D"c=
olor:rgb(206,145,120)">s"</span>)</div><div>
</div><div>
</div></div>
EnsureDispatch is a little bit slower ~4.2s compared to
~4.0s.<br>
If I don't get a performance boost with EnsureDispatch,
is there even a point using it?<br>
<br>
Thanks,<br>
Sven<br>
</div>
</div>
</div>
</div>
</div>
<br>
<fieldset></fieldset>
<pre>_______________________________________________
python-win32 mailing list
<a href=3D"mailto:[email protected]" target=3D"_blank">python-win32@p=
ython.org</a>
<a href=3D"https://mail.python.org/mailman/listinfo/python-win32" target=3D=
"_blank">https://mail.python.org/mailman/listinfo/python-win32</a>
</pre>
</blockquote>
</div>
</blockquote></div></div>
--0000000000005c43b5061d6e1e5d--
--===============7062537591709426669==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
python-win32 mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-win32
--===============7062537591709426669==--