[python-win32] Python win32Com Server DLL

Stephen Chapman schapman1974 at gmail.com
Thu Feb 16 21:16:17 EST 2017


Tim,
   Since it was a simple example I was only passing a single int for a
parameter and returning 0.  As far as I know COM servers don't cache
responses I have never seen that happen anyway.  As well I'm running on an
i7 3.2ghz machine so my results could be faster than most.

  However the question was really why in the order of magnitude is python
so much slower for the same exact call.  I have slightly changed my example
to bump the number by one to show that it is not caching.  And pass I am
passing 4 parameters now so as to show how much longer python takes as you
add more arguments.  So here are the results.  I have just done a simple
timer in this example.

*Example code:*
from comtypes.client import CreateObject
import time

do = CreateObject("testcall.dataobject1")
do2 = CreateObject("testcall.dataobject2")

def testcalltime(testname,theObj):
    first=theObj.method1(1,2,3,4)
    second=theObj.method2(1,2,3,4)
    print "Start "+testname,first,second
    a=time.time()
    for d in range (0,9999):
        first=theObj.method1(1,2,3,4)
        second=theObj.method2(1,2,3,4)
    print "End  ",testname,first,second,
    b=time.time()
    print b-a

testcalltime("Python Test",do)
testcalltime("C# Test    ",do2)

*Result output is as follows:*

Start Python Test 1 1
End   Python Test 10000 10000 0.422999858856
Start C# Test     1 1
End   C# Test     10000 10000 0.0369999408722

  So the function now bumps by one and has 4 parameters passing... So as
you can see the Python code took 11 times longer to do this simple process
If i add 5 more paramters C# only slightly goes up and Python more than
doubles.

  Also it may help to know that I'm not trying to do this to point out
deficiencies in python.  My goal is to use python for a replacement DLL I'm
building for an
application that already exists.  The program makes many calls to the DLL
which is causing a bottleneck when I use python to recreate the function
calls.  The original DLL does not seem to suffer from this either.

See both COM server examples below

*Example C# COM server: ("Register for COM Interop" Checked in build
configuration)*
using System;
using System.Runtime.InteropServices;
using testlibrary;

namespace testlibrary
{
    [ComVisible(true)]
    [Guid("DBE0E8C4-1C61-41F3-B6A4-4E2F353D3D06")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface dataobject
    {
        int method1(int test, int test2, int test3, int test4);
        int method2(int test, int test2, int test3, int test4);
    }
}

[ComVisible(true)]
[Guid("DBE0E8C4-1C61-41F3-B6A4-4E2F353D3D07")]
[ProgId("testcall.dataobject2")]
[ClassInterface(ClassInterfaceType.None)]
public class testcall : dataobject
{
    private int testcount1 = 0;
    private int testcount2 = 0;

    public int method1(int test, int test2, int test3, int test4)
    {
        testcount1 += 1;
        return testcount1;
    }
    public int method2(int test, int test2, int test3, int test4)
    {
        testcount2 += 1;
        return testcount2;
    }
}

*Example Python COM server:*
from win32com.server import register
import sys

class dataObject(object):
    _public_methods_  = ["method1","method2","startProfile","printStats"]
    _reg_progid_      = "testcall.dataobject1"
    _reg_desc_        = "simple test project"
    _reg_clsid_       = "{97dbc38f-44ce-11e2-a5e5-001018107395}"

    def __init__(self):
        self.atest1=0
        self.atest2=0

    def method1(self,*args):
        self.atest1+=1
        return self.atest1

    def method2(self,*args):
        self.atest2+=1
        return self.atest2

if __name__=='__main__':
    if len(sys.argv)>1:
        register.UnregisterServer(dataObject)
    else:
        register.UseCommandLine(dataObject)





On Thu, Feb 16, 2017 at 7:48 PM, Tim Roberts <timr at probo.com> wrote:

> Stephen Chapman wrote:
> > So after much research on the library .  It certainly looks like the
> > invoke method is taking all the time.  Is this because of the
> > conversion from Variant???
> >
> > On Tue, Feb 7, 2017 at 11:09 AM, Stephen Chapman
> > <schapman1974 at gmail.com <mailto:schapman1974 at gmail.com>> wrote:
> >
> >     Hello,
> >        I am having a speed issue while running dll functions.  I have
> >     a minimal com server example and a minimal com client example
> >     below.  I have added cProfile to the example.  All source files
> >     and the profile are attached.
> >
> >        So when I run this example I get between 1.4 seconds to 1.7
> >     seconds.  I am running a loop of 10,000 doing 2 methods in the
> >     loop.  So the here are a couple lines from the profile.
> >
> >        ncalls  tottime  percall  cumtime  percall
> >     filename:lineno(function)
> >             1    0.050    0.050    1.740    1.740
> >     cpminimaltest.py:6(testcalltime)
> >         20001    0.103    0.000    1.689    0.000 dynamic.py:41(__call__)
> >         20004    0.698    0.000    1.247    0.000
> >     automation.py:702(Invoke)
> >         80001    0.276    0.000    0.313    0.000
> >     automation.py:197(_set_value)
> >
>
> A late-bound COM call is not an efficient operation, and having it be
> out-of-process adds even more time.  20,000 calls in 0.7 seconds is 35
> microseconds per call, which is pretty ding-danged fast.  In my view,
> you have unrealistic expectations.
>
>
> >
> >     It seems like the Invoke is taking an inordinate amount of time.
> >     When I create a minimal example in C# and run the same test.  I
> >     get .009 seconds.   Is there something I am not doing right.
> >
>
> Do you mean 0.009 seconds for 20,000 calls?  I don't believe that.  How
> are you doing the timing?  Are you measuring wall-clock time or CPU
> time?  Since it's out-of-process, time spent in the server isn't going
> to be counted.  Are you sure the calls weren't optimized away?  I
> suppose it is possible that C# did the dynamic COM lookup once and
> cached the result, but even so, I can't believe 500 nanoseconds per call
> with a context switch involved.
>
> In your minimal example, are BOTH ends in C#?
>
> --
> Tim Roberts, timr at probo.com
> Providenza & Boekelheide, Inc.
>
> _______________________________________________
> python-win32 mailing list
> python-win32 at python.org
> https://mail.python.org/mailman/listinfo/python-win32
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-win32/attachments/20170216/12f49219/attachment-0001.html>


More information about the python-win32 mailing list