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 <
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

Reply via email to