[Python-Dev] Re: Prospective Peephole Transformation

2005-02-18 Thread Fredrik Lundh
Raymond Hettinger wrote:

 Based on some ideas from Skip, I had tried transforming the likes of x
 in (1,2,3) into x in frozenset([1,2,3]).  When applicable, it
 substantially simplified the generated code and converted the O(n)
 lookup into an O(1) step.  There were substantial savings even if the
 set contained only a single entry.

savings in what?  time or bytecode size?  constructed micro-benchmarks,
or examples from real-life code?

do we have any statistics on real-life n values?

/F 



___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: Prospective Peephole Transformation

2005-02-18 Thread Skip Montanaro

 Based on some ideas from Skip, I had tried transforming the likes of
 x in (1,2,3) into x in frozenset([1,2,3])

Fredrik savings in what?  time or bytecode size?  constructed
Fredrik micro-benchmarks, or examples from real-life code?

Fredrik do we have any statistics on real-life n values?

My original suggestion wasn't based on performance issues.  It was based on
the notion of tuples-as-records and lists-as-arrays.  Raymond had originally
gone through the code and changed

for x in [1,2,3]:

to 

for x in (1,2,3):

I suggested that since the standard library code is commonly used as an
example of basic Python principles (that's probably not the right word), it
should uphold that ideal tuple/list distinction.  Raymond then translated

for x in [1,2,3]:

to

for x in frozenset([1,2,3]):

I'm unclear why the list in for x in [1,2,3] or if x not in [1,2,3]
can't fairly easily be recognized as a constant and just be placed in the
constants array.  The bytecode would show n LOAD_CONST opcodes followed by
BUILD_LIST then either a COMPARE_OP (in the test case) or GET_ITER+FOR_ITER
(in the for loop case).  I think the optimizer should be able to recognize
both constructs fairly easily.

I don't know if that would provide a performance increase or not.  I was
after separation of functionality between tuples and lists.

Skip
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] Re: Prospective Peephole Transformation

2005-02-18 Thread Raymond Hettinger
 I'm unclear why the list in for x in [1,2,3] or if x not in
[1,2,3]
 can't fairly easily be recognized as a constant and just be placed in
the
 constants array. 

That part got done (at least for the if-statement).

The question is whether the type transformation idea should be carried a
step further so that a single step search operation replaces the linear
search.


Raymond
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: Prospective Peephole Transformation

2005-02-18 Thread Phillip J. Eby
At 04:45 PM 2/18/05 +0100, Fredrik Lundh wrote:
Phillip J. Eby wrote:
Only contains expressions are translated:

 if x in [1,2,3]

currently turns into:

 if x in (1,2,3)

and I'm proposing that it go one step further:

 if x in Seachset([1,2,3])

 ISTM that whenever I use a constant in-list like that, it's almost 
always with just a few (4)
 items, so it doesn't seem worth the extra effort (especially disrupting 
the marshal module) just
 to squeeze out those extra two comparisons and replace them with a 
hashing operation.

it could be worth expanding them to
if x == 1 or x == 2 or x == 3:
though...
C:\timeit -s a = 1 if a in (1, 2, 3): pass
1000 loops, best of 3: 0.11 usec per loop
C:\timeit -s a = 1 if a == 1 or a == 2 or a == 3: pass
1000 loops, best of 3: 0.0691 usec per loop
C:\timeit -s a = 2 if a == 1 or a == 2 or a == 3: pass
1000 loops, best of 3: 0.123 usec per loop
C:\timeit -s a = 2 if a in (1, 2, 3): pass
1000 loops, best of 3: 0.143 usec per loop
C:\timeit -s a = 3 if a == 1 or a == 2 or a == 3: pass
1000 loops, best of 3: 0.187 usec per loop
C:\timeit -s a = 3 if a in (1, 2, 3): pass
100 loops, best of 3: 0.197 usec per loop
C:\timeit -s a = 4 if a in (1, 2, 3): pass
100 loops, best of 3: 0.225 usec per loop
C:\timeit -s a = 4 if a == 1 or a == 2 or a == 3: pass
1000 loops, best of 3: 0.161 usec per loop
/F
Were these timings done with the code that turns (1,2,3) into a constant?
Also, I presume that these timings still include extra LOAD_FAST operations 
that could be replaced with DUP_TOP in the actual expansion, although I 
don't know how much difference that would make in practice, since saving 
the argument fetch might be offset by the need to swap and pop at the end.

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Prospective Peephole Transformation

2005-02-18 Thread M.-A. Lemburg
Raymond Hettinger wrote:
Based on some ideas from Skip, I had tried transforming the likes of x
in (1,2,3) into x in frozenset([1,2,3]).  When applicable, it
substantially simplified the generated code and converted the O(n)
lookup into an O(1) step.  There were substantial savings even if the
set contained only a single entry.  When disassembled, the bytecode is
not only much shorter, it is also much more readable (corresponding
almost directly to the original source).
The problem with the transformation was that it didn't handle the case
where x was non-hashable and it would raise a TypeError instead of
returning False as it should.  That situation arose once in the email
module's test suite.
To get it to work, I would have to introduce a frozenset subtype:
class Searchset(frozenset):
def __contains__(self, element):
try:
return frozenset.__contains__(self, element)
except TypeError:
return False
Then, the transformation would be x in Searchset([1, 2, 3]).  Since
the new Searchset object goes in the constant table, marshal would have
to be taught how to save and restore the object.
This is a more complicated than the original frozenset version of the
patch, so I would like to get feedback on whether you guys think it is
worth it.
Wouldn't it help a lot more if the compiler would detect that
(1,2,3) is immutable and convert it into a constant at
compile time ?!
The next step would then be to have Python roll out these
loops (in -O mode).
--
Marc-Andre Lemburg
eGenix.com
Professional Python Services directly from the Source  (#1, Feb 18 2005)
 Python/Zope Consulting and Support ...http://www.egenix.com/
 mxODBC.Zope.Database.Adapter ... http://zope.egenix.com/
 mxODBC, mxDateTime, mxTextTools ...http://python.egenix.com/

::: Try mxODBC.Zope.DA for Windows,Linux,Solaris,FreeBSD for free ! 
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Fixing _PyEval_SliceIndex so that integer-like objects can be used

2005-02-18 Thread Travis Oliphant
Hello again,
There is a great discussion going on the numpy list regarding a proposed 
PEP for multidimensional arrays that is in the works.

During this discussion as resurfaced regarding slicing with objects that 
are not IntegerType objects but that
have a tp_as_number-nb_int method to convert to an int. 

Would it be possible to change
_PyEval_SliceIndex  in ceval.c
so that rather than throwing an error if the indexing object is not an 
integer, the code first checks to see if the object has a
tp_as_number-nb_int method and calls it instead.

If this is acceptable, it is an easy patch.
Thanks,
-Travis Oliphant
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Fixing _PyEval_SliceIndex so that integer-like objects can be used

2005-02-18 Thread Guido van Rossum
 Would it be possible to change
 
 _PyEval_SliceIndex  in ceval.c
 
 so that rather than throwing an error if the indexing object is not an
 integer, the code first checks to see if the object has a
 tp_as_number-nb_int method and calls it instead.

I don't think this is the right solution; since float has that method,
it would allow floats to be used as slice indices, but that's not
supposed to work (to protect yourself against irreproducible results
due to rounding errors).

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Fixing _PyEval_SliceIndex so that integer-like objects can be used

2005-02-18 Thread Brett C.
Travis Oliphant wrote:
Hello again,
There is a great discussion going on the numpy list regarding a proposed 
PEP for multidimensional arrays that is in the works.

During this discussion as resurfaced regarding slicing with objects that 
are not IntegerType objects but that
have a tp_as_number-nb_int method to convert to an int.
Would it be possible to change

_PyEval_SliceIndex  in ceval.c
so that rather than throwing an error if the indexing object is not an 
integer, the code first checks to see if the object has a
tp_as_number-nb_int method and calls it instead.

You would also have to change apply_slice() since that also has a guard for 
checking the slice arguments are either NULL, int, or long objects.

But I am +1 with it since the guard is already there for ints and longs to 
handle those properly and thus the common case does not slow down in any way. 
As long as it also accepts Python objects that define __int__ and not just C 
types that have the nb_int slot defined I am okay with this idea.

-Brett
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Fix _PyEval_SliceIndex (Take two)

2005-02-18 Thread Travis Oliphant
(More readable second paragraph)
Hello again,
There is a great discussion going on the numpy list regarding a proposed 
PEP for multidimensional arrays that is in the works.

During this discussion a problem has resurfaced regarding slicing with 
objects that are not IntegerType objects but that have a 
tp_as_number-nb_int method. Would it be possible to change

_PyEval_SliceIndex  in ceval.c
so that rather than raising an exception if the indexing object is not 
an integer, the code first checks to see if the object has a 
tp_as_number-nb_int method and trys it before raising an exception.

If this is acceptable, it is an easy patch.
Thanks,
-Travis Oliphant
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Fixing _PyEval_SliceIndex so that integer-like objects can be used

2005-02-18 Thread David Ascher
On Fri, 18 Feb 2005 13:28:34 -0800, Guido van Rossum
[EMAIL PROTECTED] wrote:
  Would it be possible to change
 
  _PyEval_SliceIndex  in ceval.c
 
  so that rather than throwing an error if the indexing object is not an
  integer, the code first checks to see if the object has a
  tp_as_number-nb_int method and calls it instead.
 
 I don't think this is the right solution; since float has that method,
 it would allow floats to be used as slice indices, but that's not
 supposed to work (to protect yourself against irreproducible results
 due to rounding errors).

I wonder if floats are the special case here, not integer like objects.

I've never been particularly happy about the confusion between the two
roles of int() and it's C equivalents, i.e. casting and conversion.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Fixing _PyEval_SliceIndex so that integer-like objects can be used

2005-02-18 Thread Bob Ippolito
On Feb 18, 2005, at 4:36 PM, David Ascher wrote:
On Fri, 18 Feb 2005 13:28:34 -0800, Guido van Rossum
[EMAIL PROTECTED] wrote:
Would it be possible to change
_PyEval_SliceIndex  in ceval.c
so that rather than throwing an error if the indexing object is not 
an
integer, the code first checks to see if the object has a
tp_as_number-nb_int method and calls it instead.
I don't think this is the right solution; since float has that method,
it would allow floats to be used as slice indices, but that's not
supposed to work (to protect yourself against irreproducible results
due to rounding errors).
I wonder if floats are the special case here, not integer like 
objects.

I've never been particularly happy about the confusion between the two
roles of int() and it's C equivalents, i.e. casting and conversion.
All of the __special__ methods for this purpose seem to be usable only 
for conversion, not casting (__str__, __unicode__, etc.).  The only way 
I've found to pass for a particular value type is to subclass one.   We 
do this a lot in PyObjC.

It ends up being a net win anyway, because you get free implementations 
of all the relevant methods, at the expense of having two copies of the 
value.  The fact that these proxy objects are no longer 
visible-from-Python subclasses of Objective-C objects isn't really a 
big deal in our case, because the canonical Objective-C way to checking 
inheritance still work.  The wrapper types use an attribute protocol 
for casting (__pyobjc_object__), and delegate to this object with 
__getattr__.

 from Foundation import *
 one = NSNumber.numberWithInt_(1)
 type(one).mro()
[class 'objc._pythonify.OC_PythonInt', type 'int', type 'object']
 isinstance(one, NSNumber)
False
 isinstance(one.__pyobjc_object__, NSNumber)
True
 one.isKindOfClass_(NSNumber)
1
 type(one)
class 'objc._pythonify.OC_PythonInt'
 type(one.__pyobjc_object__)
objective-c class NSCFNumber at 0x300620
-bob
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Windows Low Fragementation Heap yields speedup of ~15%

2005-02-18 Thread Evan Jones
On Thu, 2005-02-17 at 22:38, Tim Peters wrote:
Then you allocate a small object, marked 's':
bbbsfff
Isn't the whole point of obmalloc is that we don't want to allocate s 
on the heap, since it is small? I guess s could be an object that 
might potentially grow.

One thing to take from that is that LFH can't be helping list-growing
in a direct way either, if LFH (as seems likely) also needs to copy
objects that grow in order to keep its internal memory segregated by
size.  The indirect benefit is still available, though:  LFH may be
helping simply by keeping smaller objects out of the general heap's
hair.
So then wouldn't this mean that there would have to be some sort of 
small object being allocated via the system malloc that is causing the 
poor behaviour? As you mention, I wouldn't think it would be list 
objects, since resizing lists using LFH should be *worse*. That would 
actually be something that is worth verifying, however. It could be 
that the Windows LFH is extra clever?

I'm afraid the only you can know for sure is by obtaining detailed
memory maps and analyzing them.
Well, it would also be useful to find out what code is calling the 
system malloc. This would make it easy to examine the code and see if 
it should be calling obmalloc or the system malloc. Any good ideas for 
easily obtaining this information? I imagine that some profilers must 
be able to produce a complete call graph?

Evan Jones
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Memory Allocator Part 2: Did I get it right?

2005-02-18 Thread Evan Jones
Sorry for taking so long to get back to this thread, it has been one of 
those weeks for me.

On Feb 16, 2005, at 2:50, Martin v. Löwis wrote:
Evan then understood the feature, and made it possible.
This is very true: it was a very useful exercise.
I can personally accept breaking the code that still relies on the
invalid APIs. The only problem is that it is really hard to determine
whether some code *does* violate the API usage.
Great. Please ignore the patch on SourceForge for a little while. I'll 
produce a revision 3 this weekend, without the compatibility hack.

Evan Jones
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Fixing _PyEval_SliceIndex so that integer-like objects can be used

2005-02-18 Thread Travis Oliphant
Guido van Rossum wrote:
Would it be possible to change
_PyEval_SliceIndex  in ceval.c
so that rather than throwing an error if the indexing object is not an
integer, the code first checks to see if the object has a
tp_as_number-nb_int method and calls it instead.
   

I don't think this is the right solution; since float has that method,
it would allow floats to be used as slice indices, 
 

O.K.,
then how about if arrayobjects can make it in the core, then a check for 
a rank-0 integer-type
arrayobject is allowed before raising an exception?

-Travis
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Windows Low Fragementation Heap yields speedup of ~15%

2005-02-18 Thread Tim Peters
[Tim Peters]
...
 Then you allocate a small object, marked 's':

 bbbsfff

[Evan Jones]
 Isn't the whole point of obmalloc

No, because it doesn't matter what follows that introduction: 
obmalloc has several points, including exploiting the GIL, heuristics
aiming at reusing memory while it's still high in the memory
heirarchy, almost never touching a piece of memory until it's actually
needed, and so on.

 is that we don't want to allocate s on the heap, since it is small?

That's one of obmalloc's goals, yes.  But small is a relative
adjective, not absolute.  Because we're primarily talking about LFH
here, the natural meaning for small in _this_ thread is  16KB,
which is much larger than small means to obmalloc.  The memory-map
example applies just well to LFH as to obmalloc, by changing which
meaning for small you have in mind.

 I guess s could be an object that might potentially grow.

For example, list guts in Python are never handled by obmalloc,
although the small fixed-size list _header_ object is always handled
by obmalloc.

 One thing to take from that is that LFH can't be helping list-growing
 in a direct way either, if LFH (as seems likely) also needs to copy
 objects that grow in order to keep its internal memory segregated by
 size.  The indirect benefit is still available, though:  LFH may be
 helping simply by keeping smaller objects out of the general heap's
 hair.

 So then wouldn't this mean that there would have to be some sort of
 small object being allocated via the system malloc that is causing the
 poor behaviour?

Yes.  For example, a 300-character string could do it (that's not
small to obmalloc, but is to LFH).  Strings produced by pickling are
very often that large, and especially in Zope (which uses pickles
extensively under the covers -- reading and writing persistent objects
in Zope all involve pickle strings).

 As you mention, I wouldn't think it would be list objects, since resizing
 lists using LFH should be *worse*.

Until they get to LFH's boundary for small, and we have only the
vaguest idea what Martin's app does here -- we know it grows lists
containing 50K elements in the end, and ... well, that's all I really
know about it wink.

A well-known trick is applicable in that case, if Martin thinks it's
worth the bother:
grow the list to its final size once, at the start (overestimating if
you don't know for sure).  Then instead of appending, keep an index to
the next free slot, same as you'd do in C.  Then the list guts never
move, so if that doesn't yield the same kind of speedup without using
LFH, list copying wasn't actually the culprit to begin with.

 That would actually be something that is worth verifying, however.

Not worth the time to me -- Windows is closed-source, and I'm too old
to enjoy staring at binary disassemblies any more.  Besides, list guts
can't stay in LFH after the list exceeds 4K elements.  If list-copying
costs are significant here, they're far more likely to be due to
copying lists over 4K elements than under -- copying a list takes
O(len(list)) time.  So the realloc() strategy used by LFH _probably_
isn't of _primary)_ interest here.

 It could be that the Windows LFH is extra clever?

Sure -- that I doubt it moves Heaven  Earth to cater to reallocs is
just educated guessing.  I wrote my first production heap manager at
Cray Research, around 1979 wink.

 ...
 Well, it would also be useful to find out what code is calling the
 system malloc. This would make it easy to examine the code and see if
 it should be calling obmalloc or the system malloc. Any good ideas for
 easily obtaining this information? I imagine that some profilers must
 be able to produce a complete call graph?

Windows supports extensive facilities for analyzing heap usage, even
from an external process that attaches to the process you want to
analyze.  Ditto for profiling.  But it's not easy, and I don't know of
any free tools that are of real help.  If someone were motivated
enough, it would probably be easiest to run Martin's app on a Linux
box, and use the free Linux tools to analyze it.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Windows Low Fragementation Heap yields speedup of ~15%

2005-02-18 Thread Evan Jones
On Feb 18, 2005, at 17:51, Tim Peters wrote:
grow the list to its final size once, at the start (overestimating if
you don't know for sure).  Then instead of appending, keep an index to
the next free slot, same as you'd do in C.  Then the list guts never
move, so if that doesn't yield the same kind of speedup without using
LFH, list copying wasn't actually the culprit to begin with.
If this *does* improve the performance of his application by 15%, that  
would strongly argue for an addition to the list API similar to Java's  
ArrayList.ensureCapacity or the STL's vectorT::reserve. Since the  
list implementation already maintains separate ints for the list array  
size and the list occupied size, this would really just expose this  
implementation detail to Python. I don't like revealing the  
implementation in this fashion, but if it does make a significant  
performance difference, it could be worth it.

http://java.sun.com/j2se/1.5.0/docs/api/java/util/ 
ArrayList.html#ensureCapacity(int)
http://www.sgi.com/tech/stl/Vector.html#4

Evan Jones
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Re: Re: Re: Prospective Peephole Transformation

2005-02-18 Thread Tim Peters
[Phillip J. Eby]
 Still, it's rather interesting that tuple.__contains__ appears slower than a
 series of LOAD_CONST and == operations, considering that the tuple
 should be doing basically the same thing, only without bytecode fetch-and-
 decode overhead.  Maybe it's tuple.__contains__ that needs optimizing
 here?

[Fredrik Lundh]
 wouldn't be the first time...

How soon we forget wink.  Fredrik introduced a pile of optimizations
special-casing the snot out of small integers into ceval.c a long time
ago, like this in COMPARE_OP:

case COMPARE_OP:
w = POP();
v = TOP();
if (PyInt_CheckExact(w)  PyInt_CheckExact(v)) {
/* INLINE: cmp(int, int) */
register long a, b;
register int res;
a = PyInt_AS_LONG(v);
b = PyInt_AS_LONG(w);
switch (oparg) {
case PyCmp_LT: res = a   b; break;
case PyCmp_LE: res = a = b; break;
case PyCmp_EQ: res = a == b; break;
case PyCmp_NE: res = a != b; break;
case PyCmp_GT: res = a   b; break;
case PyCmp_GE: res = a = b; break;
case PyCmp_IS: res = v == w; break;
case PyCmp_IS_NOT: res = v != w; break;
default: goto slow_compare;
}
x = res ? Py_True : Py_False;
Py_INCREF(x);
}
else {
  slow_compare:
x = cmp_outcome(oparg, v, w);
}

That's a hell of a lot faster than tuple comparison's deferral to
PyObject_RichCompareBool can be, even if we inlined the same blob
inside the latter (then we'd still have the additional overhead of
calling PyObject_RichCompareBool).  As-is, PyObject_RichCompareBool()
has to do (relatively) significant work just to out find which
concrete comparision implementation to call.

As a result, i == j in Python source code, when i and j are little
ints, is much faster than comparing i and j via any other route in
Python.  That's mostly really good, IMO -- /F's int optimizations are
of major value in real life.  Context-dependent optimizations make
code performance less predictable too -- that's life.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] Prospective Peephole Transformation

2005-02-18 Thread Raymond Hettinger
 Wouldn't it help a lot more if the compiler would detect that
 (1,2,3) is immutable and convert it into a constant at
 compile time ?!
 
 
  Yes.  We've already gotten it to that point:
 . . .
 
 Cool. Does that work for all tuples in the program ?

It is limited to just tuples of constants (strings, ints, floats,
complex, None, and other tuples).  Also, it is limited in its ability to
detect a nesting like: a=((1,2),(3,4)).  One other limitation is that
floats like -0.23 are not recognized as constants because the initial
compilation still produces a UNARY_NEGATIVE operation:

 dis.dis(compile('-0.23', '', 'eval'))
  0   0 LOAD_CONST   0 (0.23001)
  3 UNARY_NEGATIVE  
  4 RETURN_VALUE



 I did a search on our code and Python's std lib. It turns
 out that by far most such usages use either 2 or 3
 values in the tuple. If you look at the types of the
 values, the most common usages are strings and integers.

Right, those are the most common cases.  The linear searches are
ubiquitous.  Here's a small selection:

if comptype not in ('NONE', 'ULAW', 'ALAW', 'G722')
return tail.lower() in (.py, .pyw)
assert n in (2, 3, 4, 5)
if value[2] in ('F','n','N')
if sectName in (temp, cdata, ignore, include, rcdata)
if not decode or encoding in ('', '7bit', '8bit', 'binary'):
if (code in (301, 302, 303, 307) and m in (GET, HEAD)

Unfortunately, there are several common patterns that are skipped
because rarely changed globals/builtins cannot be treated as constants:
if isinstance(x, (int, float, complex)):  # types are not constants
if op in (ROT_TWO, POP_TOP, LOAD_FAST):   # global consts from
opcode.py
except (TypeError, KeyError, IndexError): # builtins are not
constant



 I'd assume that you'll get somewhat different results
 from your benchmark if you had integers in the tuple.

Nope, the results are substantially the same give or take 2usec.


 
 Hmm, what if you'd teach tuples to do faster contains lookups for
 string or integer only content, e.g. by introducing sub-types for
 string-only and integer-only tuples ?!

For a linear search, tuples are already pretty darned good and leave
room for only microscopic O(n) improvements.  The bigger win comes from
using a better algorithm and data structure -- hashing beats linear
search hands-down.  The constant search time is faster for all n1,
resulting in much improved scalability.  No tweaking of
tuple.__contains__() can match it.

Sets are the right data structure for fast membership testing.  I would
love for sets to be used internally while letting users continue to
write the clean looking code shown above.



Raymond
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Prospective Peephole Transformation

2005-02-18 Thread Tim Peters
[Raymond Hettinger]
 ...
 The problem with the transformation was that it didn't handle the case
 where x was non-hashable and it would raise a TypeError instead of
 returning False as it should.

I'm very glad you introduced the optimization of building small
constant tuples at compile-time.  IMO, that was a pure win.

I don't like this one, though.  The meaning of x in (c1, c2, ...,
c_n) is x == c1 or x == c2  or ... or x == c_n, and a
transformation that doesn't behave exactly like the latter in all
cases is simply wrong.  Even if x isn't hashable, it could still be of
a type that implements __eq__, and where x.__eq__(c_i) returned True
for some i, and then False is plainly the wrong result.  It could also
be that x is of a type that is hashable, but where x.__hash__() raises
TypeError at this point in the code.  That could be for good or bad
(bug) reasons, but suppressing the TypeError and converting into False
would be a bad thing regardless.

 That situation arose once in the email module's test suite.

I don't even care if no code in the standard library triggered a
problem here:  the transformation isn't semantically correct on the
face of it.  If we knew the type of x at compile-time, then sure, in
most (almost all) cases we could know it was a safe transformation
(and even without the hack to turn TypeError into False).  But we
don't know now, so the worst case has to be assumed:  can't do this
one now.  Maybe someday, though.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Windows Low Fragementation Heap yields speedup of ~15%

2005-02-18 Thread Tim Peters
[Tim Peters]
 grow the list to its final size once, at the start (overestimating if
 you don't know for sure).  Then instead of appending, keep an index to
 the next free slot, same as you'd do in C.  Then the list guts never
 move, so if that doesn't yield the same kind of speedup without using
 LFH, list copying wasn't actually the culprit to begin with.

[Evan Jones]
 If this *does* improve the performance of his application by 15%, that
 would strongly argue for an addition to the list API similar to Java's
 ArrayList.ensureCapacity or the STL's vectorT::reserve. Since the
 list implementation already maintains separate ints for the list array
 size and the list occupied size, this would really just expose this
 implementation detail to Python. I don't like revealing the
 implementation in this fashion, but if it does make a significant
 performance difference, it could be worth it.

That's a happy thought!  It was first suggested for Python in 1991
wink, but before Python 2.4 the list implementation didn't have
separate members for current size and capacity, so can't get there
from here was the only response.  It still wouldn't be trivial,
because nothing in listobject.c now believes the allocated size ever
needs to be preserved, and all len()-changing list operations ensure
that not too much overallocation remains (see list_resize() in
listobject.c for details).

But let's see whether it would help first.
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Proposal for a module to deal with hashing

2005-02-18 Thread Nick Coghlan
Gregory P. Smith wrote:
fyi - i've updated the python sha1/md5 openssl patch.  it now replaces
the entire sha and md5 modules with a generic hashes module that gives
access to all of the hash algorithms supported by OpenSSL (including
appropriate legacy interface wrappers and falling back to the old code
when compiled without openssl).
 
https://sourceforge.net/tracker/index.php?func=detailaid=1121611group_id=5470atid=305470
I don't quite like the module name 'hashes' that i chose for the
generic interface (too close to the builtin hash() function).  Other
suggestions on a module name?  'digest' comes to mind.
'hashtools' and 'hashlib' would both have precedents in the standard library 
(itertools and urllib, for example).

It occurs to me that such a module would provide a way to fix the bug with 
incorrectly hashable instances of new-style classes:

Py class C:
... def __eq__(self, other): return True
...
Py hash(C())
Traceback (most recent call last):
  File stdin, line 1, in ?
TypeError: unhashable instance
Py class C(object):
...   def __eq__(self, other): return True
...
Py hash(C())
10357232
Guido wanted to fix this by eliminating object.__hash__, but that caused 
problems for Jython. If I remember that discussion correctly, the problem was 
that, in Jython, the default hash is _not_ simply hash(id(obj)) the way it is in 
CPython, so Python code needs a way to get access to the default implementation. 
A hashtools.default_hash that worked like the current object.__hash__ would seem 
to provide such a spelling, and allow object.__hash__ to be removed (fixing the 
above bug).

Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] Prospective Peephole Transformation

2005-02-18 Thread Raymond Hettinger
 I'm very glad you introduced the optimization of building small
 constant tuples at compile-time.  IMO, that was a pure win.

It's been out in the wild for a while now with no issues.  I'm somewhat
happy with it.



  the transformation isn't semantically correct on the
 face of it.

Well that's the end of that.

What we really need is a clean syntax for specifying a constant
frozenset without compiler transformations of tuples.  That would have
the further advantage of letting builtins and globals be used as element
values.

   if isinstance(x, {int, float, complex}):
   if opcode in {REPEAT, MIN_REPEAT, MAX_REPEAT}:
   if (code in {301, 302, 303, 307} and m in {GET, HEAD}:
   if op in (ROT_TWO, POP_TOP, LOAD_FAST)

Perhaps something other notation would be better but the idea is
basically the same.



Raymond
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Requesting that a class be a new-style class

2005-02-18 Thread Nick Coghlan
This is something I've typed way too many times:
Py class C():
  File stdin, line 1
class C():
^
SyntaxError: invalid syntax
It's the asymmetry with functions that gets to me - defining a function with no 
arguments still requires parentheses in the definition statement, but defining a 
class with no bases requires the parentheses to be omitted.

Which leads in to the real question: Does this *really* need to be a syntax 
error? Or could it be used as an easier way to spell class C(object):?

Then, in Python 3K, simply drop support for omitting the parentheses from class 
definitions - require inheriting from ClassicClass instead. This would also have 
the benefit that the elimination of defaulting to classic classes would cause a 
syntax error rather than subtle changes in behaviour.

Cheers,
Nick.
--
Nick Coghlan   |   [EMAIL PROTECTED]   |   Brisbane, Australia
---
http://boredomandlaziness.skystorm.net
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] builtin_id() returns negative numbers

2005-02-18 Thread Donovan Baarda

From: Armin Rigo [EMAIL PROTECTED]
 Hi Tim,


 On Thu, Feb 17, 2005 at 01:44:11PM -0500, Tim Peters wrote:
  256 ** struct.calcsize('P')
 
  Now if you'll just sign and fax a Zope contributor agreement, I'll
  upgrade ZODB to use this slick trick wink.

 I hereby donate this line of code to the public domain :-)

Damn... we can't use it then!

Seriously, on the Python lists there has been a discussion rejecting an
md5sum implementation because the author donated it to the public domain.
Apparently lawyers have decided that you can't give code away. Intellectual
charity is illegal :-)


Donovan Baardahttp://minkirri.apana.org.au/~abo/


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] license issues with profiler.py and md5.h/md5c.c

2005-02-18 Thread Donovan Baarda
From: Martin v. Löwis [EMAIL PROTECTED]
 Donovan Baarda wrote:
  This patch keeps the current md5c.c, md5module.c files and adds the
  following; _hashopenssl.c, hashes.py, md5.py, sha.py.
 [...]
  If all we wanted to do was fix the md5 module

 If we want to fix the licensing issues with the md5 module, this patch
 does not help at all, as it keeps the current md5 module (along with
 its licensing issues). So any patch to solve the problem will need
 to delete the code with the questionable license.

It maybe half fixes it in that if Python is happy with the RSA one, they can
continue to include it, and if Debian is unhappy with it, they can remove it
and build against openssl.

It doesn't fully fix the license problem. It is still worth considering
because it doesn't make it worse, and it does allow Python to use much
faster implementations and support other digest algorithms when openssl is
available.

 Then, the approach in the patch breaks the promise that the md5 module
 is always there. It would require that OpenSSL is always there - a
 promise that we cannot make (IMO).

It would be better if found an alternative md5c.c. I found one that was the
libmd implementation that someone mildly tweaked and then slapped an LGPL
on. I have a feeling that would make the lawyers tremble more than the
public domain libmd one, unless they are happy that someone else is
prepared to wear the grief for slapping a LGPL onto something public domain.

Probably the best at the moment is the sourceforge one, which is listed as
having a zlib/libpng licence.


Donovan Baardahttp://minkirri.apana.org.au/~abo/


___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] license issues with profiler.py and md5.h/md5c.c

2005-02-18 Thread Gregory P. Smith
On Fri, Feb 18, 2005 at 10:06:24AM +0100, Martin v. L?wis wrote:
 Donovan Baarda wrote:
 This patch keeps the current md5c.c, md5module.c files and adds the
 following; _hashopenssl.c, hashes.py, md5.py, sha.py.
 [...]
 If all we wanted to do was fix the md5 module
 
 If we want to fix the licensing issues with the md5 module, this patch
 does not help at all, as it keeps the current md5 module (along with
 its licensing issues). So any patch to solve the problem will need
 to delete the code with the questionable license.
 
 Then, the approach in the patch breaks the promise that the md5 module
 is always there. It would require that OpenSSL is always there - a
 promise that we cannot make (IMO).

I'm aware of that.

My goals are primarily to get a good openssl based hashes/digest
module going to be used instead of the built in implementations when
openssl available because openssl is -so- much faster.  Fixing the
debian instigated md5 licensing issue is secondary and is something
I'll get to later on after i work on the fun stuff.

And as Donovan has said, the patch already does present debian with
the option of dropping that md5 module and using the openssl derived
one instead if they're desperate.  based on laziness winning and the
issue being so minor i hope they just wait for a patch from me that
replaces the md5c.c with one of the acceptably licensed ones for their
2.3/2.4 packages.

-g

___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Requesting that a class be a new-style class

2005-02-18 Thread Alex Martelli
On 2005 Feb 19, at 06:03, Nick Coghlan wrote:
This is something I've typed way too many times:
Py class C():
  File stdin, line 1
class C():
^
SyntaxError: invalid syntax
It's the asymmetry with functions that gets to me - defining a 
function with no arguments still requires parentheses in the 
definition statement, but defining a class with no bases requires the 
parentheses to be omitted.
Seconded.  It's always irked me enough that it's the only ``apology'' 
for Python syntax you'll see in the Nutshell -- top of p. 71, The 
syntax of the class statement has a small, tricky difference from that 
of the def statement etc.

Which leads in to the real question: Does this *really* need to be a 
syntax error? Or could it be used as an easier way to spell class 
C(object):?
-0 ... instinctively, I dread the task of explaining / teaching about 
the rationale for this somewhat kludgy transitional solution [[empty 
parentheses may be written OR omitted, with large difference in 
meaning, not very related to other cases of such parentheses]], even 
though I think you're right that it would make the future transition to 
3.0 somewhat safer.

Alex
___
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com