On Saturday 03 July 2004 09:20 pm, Fernando Jorge Silveira Filho wrote:
> Below is a simplified code that suffers from the same problem. On the
> other side, I agree that I may be wrong about blaming the interface
> between C++ and Python for degrading the performance in this particular
> case. However, this is just what my intuition (which is wrong no less
> than often :-)) tells me. It seems to me that if the Qt library had
> support for numerical key comparisions within itself the whole process
> would be faster without so many changes between C++ and Python code.

I replied too quickly; the docs say that reimplementing compare() is 
preferable and more efficient than key().

>From what I've read over the years, python code performance is primarily 
affected by:

1.      algorithms and design
2.      attribute lookups
3.      function calls
4.      python-c boundary crosses

There's nothing you can do about the first one in this case, but you can try 
to minimize the others.

In the case of  "self.key( col, ascending ).toInt( )" it's two attribute 
lookups, two function calls, and one extension call.  Disassembling this 
confirms it:

[1] >>> def compare(self, item, column, ascending):
   ...:     x = self.key(column, ascending).toInt()

[2] >>> import dis
[3] >>> dis.dis(compare)
  2           0 LOAD_FAST                0 (self)
              3 LOAD_ATTR                1 (key)
              6 LOAD_FAST                2 (column)
              9 LOAD_FAST                3 (ascending)
             12 CALL_FUNCTION            2
             15 LOAD_ATTR                4 (toInt)
             18 CALL_FUNCTION            0
             21 STORE_FAST               4 (x)
             24 LOAD_CONST               0 (None)
             27 RETURN_VALUE

(the boundary cross isn't there, of course)

>     # C++ Prototype
>     # int MyListViewItem::compare( QListViewItem *i, int col,
>     #                             bool ascending ) const
>     def compare( self, i, col, ascending ):
>         x = self.key( col, ascending ).toInt( );
>         y = i.key( col, ascending).toInt( );
>         return x[0]-y[0];

Now, you've already implemented 'compare()' in python, so one thing  you want 
to avoid is crossing the extension boundary again, as pyqt has already called 
into your python code.  Instead of calling key() twice,  then toInt() twice, 
you could do:

    def compare(self, item, column, ascending):
        try:
            a = int(str(self.text(column))) 
        except (ValueError, ):
            a = self.text(column)
        try:
            b = int(str(item.text(column)))
        except:
            b = item.text(column)
        return cmp(a, b)

I've tested this on a list view of mine, and it works with small data sets.  
Could you try it and see if it's better or worse with your data?  You might 
try timing the header click slot.


-- 
Troy Melhase, [EMAIL PROTECTED]
--
I have sworn upon the altar of God eternal hostility against every form of 
tyranny over the mind of man. - Thomas Jefferson

_______________________________________________
PyKDE mailing list    [EMAIL PROTECTED]
http://mats.imk.fraunhofer.de/mailman/listinfo/pykde

Reply via email to