[python-win32] Dispatch vs EnsureDispatch performance

2024-04-17 Thread Sven Bardos via python-win32
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 list
python-win32@python.org
https://mail.python.org/mailman/listinfo/python-win32


Re: [python-win32] Dispatch vs EnsureDispatch performance

2024-07-17 Thread Sven Bardos via python-win32
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)
...
10.0000.0000.0250.025 __init__.py:572(_ApplyTypes_)
10.0000.0000.0070.007 __init__.py:603(_get_good_object_)
141950.0010.0000.0010.000
__init__.py:608(_get_good_single_object_)
14198/10.0050.0000.0070.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 <
skippy.hamm...@gmail.com>:

> 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 
> listpython-win32@python.orghttps://mail.python.org/mailman/listinfo/python-win32
>
>
___
python-win32 mailing list
python-win32@python.org
https://mail.python.org/mailman/listinfo/python-win32