This common idiom actually works against our reflect optimization of built-in 
methods, but we still make it work.

Just to give you (and anyone else curious) an overview of this:  We have a 
piece of code called the ReflectOptimizer which generates an optimized call to 
.NET methods.  The way it does this is it generates code for doing type checks 
for all the possible overloads of a method and emits that all into one method.  
Then when you call from Python we dispatch to this helper method, which can do 
a bunch of efficient type checks, and finally dispatch to the correct method.

Creating these methods isn't cheap, so we defer this until the first invocation 
of a method.  At that point in time we replace the callers method (in whatever 
dictionary they were in) with the new optimized method.

When someone follows the common idiom we cannot successfully back patch the 
reference to the method, so instead the non-optimized method needs to remember 
that it's been optimized and use the optimized method instead.  Eventually the 
local copy will go out of scope, and we'll be left w/ only the optimized 
version.

The back-patching is what's potentially problematic: If we get that 
back-patching wrong then we'll continuously re-optimize methods over and over 
again.  That obviously kills performance, which is what I suspect is going on 
here.

Now strangely enough because the work we do to make this common idiom still be 
efficient this could actually be a way to work around the back-patching bug, if 
that is indeed what we're seeing.

________________________________________
From: [EMAIL PROTECTED] On Behalf Of J. Merrill
Sent: Thursday, May 25, 2006 9:29 AM
To: Discussion of IronPython
Subject: Re: [IronPython] Optimized methods and serious performance  issues

I know almost nothing about DirectX, am definitely not a Python guru, and have 
not experimented with IP in this area.  However, my impression is that there is 
a common Python "idiom" for speeding up method calls, which is to use a 
variable (often a local) to hold a reference to a "bound method" and make calls 
through that variable.  This avoids all the work that normally has to be done 
to figure out what actual method (the one associated with the instance, the 
class, the parent class, the parent class's parent, etc etc) is supposed to be 
called by a particular "callable" expression.

Whether this is appropriate in your case, I can't say.  For example, if the 
value of self.mesh can change while your loop is running, it won't give the 
right results to do
    methref = self.mesh.DrawSubset
and then call
    methref(0)
in your loop, because this will call via whatever value mesh had been when you 
set methref.

If it's appropriate, have you tried that technique?

At 11:33 AM 5/25/2006, Jonathan Jacobs wrote
>(Please disregard any earlier message about this, I think I might have pressed
>"Send" accidentally.)
>
>Hi,
>
>I ran across some "interesting" behaviour today.
>
>Short version:
>I have a handful of Direct3D.Mesh objects (courtesy of Direct3D.Mesh.Teapot)
>which I render using self.meshInstance.DrawSubset(0). I've been experiencing
>pretty serious performance issues, so I did a bit of testing and this is what
>I came up with:
>
>(The averages are accumulated every call and averaged (and output) every 500
>calls, a small value is obviously better, all values are in milliseconds.)
>
>No drawing calls:
>running average: 0.0236448413598 ms
>running average: 0.0229452898402 ms
>running average: 0.0236400825059 ms
>running average: 0.0257713352135 ms
>
>No drawing calls, -X:NoOptimize:
>running average: 0.0251883756139
>running average: 0.0250299057799
>running average: 0.0224732115359
>running average: 0.0225412631463
>
>self.mesh.DrawSubset(0):
>running average: 3.40948918622 ms
>running average: 3.45289207504 ms
>running average: 3.43480367147 ms
>running average: 3.45502784866 ms
>
>self.mesh.DrawSubset(0), -X:NoOptimize:
>running average: 0.111673644441 ms
>running average: 0.118880928633 ms
>running average: 0.134856876975 ms
>running average: 0.11670232533 ms
>
>Helper.DrawMesh(self.mesh, 0):
>running average: 0.0415348007294 ms
>running average: 0.0328241945979 ms
>running average: 0.0296612223703 ms
>running average: 0.0330559507815 ms
>
>Helper.DrawMesh(self.mesh, 0), -X:NoOptimize:
>running average: 0.063753413583 ms
>running average: 0.0668509515698 ms
>running average: 0.0603922350916 ms
>running average: 0.070181197511 ms
>
>Helper.DrawMesh is my own function implemented in C#:
>public class Helper {
>   public static void DrawMesh(Microsoft.DirectX.Direct3D.Mesh mesh, int id) {
>     mesh.DrawSubset(id);
>   }
>}
>
>I'm interested as to why the self.mesh.DrawSubset call is so disappointingly
>slow and why it is sped up by *disabling* method optimization.
>
>Unfortunately, it is laborious for me to separate the useful code from the
>not-so-useful code and I'm not sure how to reproduce this outside of DirectX.
>I can take some time out to try and cut this down to the bare essentials if
>need be.
>
>Regards
>--
>Jonathan
>
>When you meet a master swordsman,
>show him your sword.
>When you meet a man who is not a poet,
>do not show him your poem.
>                 -- Rinzai, ninth century Zen master


J. Merrill / Analytical Software Corp


_______________________________________________
users mailing list
[email protected]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
_______________________________________________
users mailing list
[email protected]
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com

Reply via email to