Help with a Python ASP C extension module ...

Eric Vasilik eric at vasilik.com
Sun Mar 17 19:58:46 EST 2002


Thanks Mark, you nailed *exactly* what I'm looking for!  I will try to
use this asap.  I am using Response.BinaryWrite to send an image to
the client.  To test the performance of my own writes, I have two web
pages.  One has 30 images all directly hitting JPEGs on my server. 
The second page has references to the same 30 images, but using a url
which causes the server to go to a python script which writes the
JPEGs out.  By eyeballing the amount of time it takes to completely
load both pages, I see that it takes almost 3 times as long to load
the page which goes thorugh the script.

I'm not sure where the bottleneck is, I'm trying to rule out the GIL
by doing my own call to IResponse.BinaryWrite.  However, as you point
out, there may be other factors.  I have to track down some:

1) I'm using a custom 404 error handler to invoke the script.  Perhaps
there is some single threading issues there?  Probably not, I would
think that IIS can hand out plenty of errors without locking all
threads out.

2) I'm not sending the right caching headers out to the client and the
client is refetching all the images all the time, while the direct
JPEG page fetches them from the cache.  This is a real possibilty I'll
have to track down.

I'll post back when (if :-) I find out!

P.S. I'm eagerly awaiting the arrival of your book "Python Programming
on Win32"!

- Eric

Mark Hammond <mhammond at skippinet.com.au> wrote in message news:<3C93F993.3010109 at skippinet.com.au>...
> Eric Vasilik wrote:
> > I am writing a C extension to Python.  The reason I am writing an
> > extension is that I believe that the implementation of
> > Response.BinaryWrite() in the Window's ASP extension (I am using
> > Active State's Python 2.1) is not releasing the global interpreter
> > lock.  
> 
> I am almost certain that it does.  All COM calls release the GIL. 
> Response is an IDispatch object.  This means that the call is made via 
> either PyIDispatch::Invoke, or PyIDispatch::InvokeTypes.  These release 
> the lock.
> 
>  > I am getting very poor performace using it and I believe that
> > my server is not taking advantage of writing out multiple streams
> > because of the global lock.
> 
> I am not sure what makes you believe Reponse.Write is to blame.  It is 
> more likely that another Python thread is "busy" somewhere other than 
> Response.Write or fileIO.
> 
> > Instead of writing out a response with:
> > 
> >     Response.BinaryWrite( buffer( open( fileName, 'rb' ).read() ) )
> > 
> > I am now doing the following:
> > 
> >     PythonExt.binaryWriteFile( Response, fileName )
> 
> OK - but don't be surprised if you see pretty much the same thing.  You 
> are removing a little Python overhead, but not alot.
> 
> > The difference between these two is that the first calls the default
> > implementation of Response.BinaryWrite and the second calls an
> > extension I have written which reads the file and writes it out to
> > response, all while the interpreter lock is released.
> 
> The former Python version will do all the significant work (ie, the file 
> open, read and response.write call) with the lock released too.  Some of 
> the IDispatch mechanics will be avoided though, as will the multiple 
> lock transitions involved in the Python version.
> 
> > My problem, is I cannot find any documentation on how to get a hold of
> > the IResponse object from the Python Response object.  I need to get
> > it so that I may call BinaryWrite on without going back into the
> > Python interpreter.
> 
> Going via IResponse should speed things up a tiny bit too.  Basically, 
> the "Response" object is a class instance, and the attribute "_oleobj_" 
> is the PyIDispatch object.  So you need something like:
> 
>    if (!PyArg_ParseTuple("Os", &pyResponse, &filename)) ...
>    PyObject *pydisp = PyObject_GetAttrString(pyResponse, "_oleobj_");
>    if (!pydisp) ...
>    // now get the object.
>    if (!PyCom_InterfaceFromPyObject(pydisp,
>            IID_IRESPONSE,
>            (void **)&pResponse,
>            FALSE /* None is not valid */ )) ...
>     Py_DECREF(pydisp);
>     ... use pResponse
>     pResponse->Release();
> 
> 
> Using PyCom_InterfaceFromPyObject() means you will need to include 
> pythoncom.h, and link against pythoncomxx.lib - which means you will 
> need to build pythoncom from sources - see 
> http://starship.python.net/crew/mhammond/win32/BuildingExtensions.html
> 
> Mark.



More information about the Python-list mailing list