Bob Greschke wrote: > On 2008-04-21 14:50:13 -0600, Ivan Illarionov <[EMAIL PROTECTED]> said: > >> On 22 апр, 00:10, Ivan Illarionov <[EMAIL PROTECTED]> wrote: >>> On 20 ÁÐÒ, 04:10, George Sakkis <[EMAIL PROTECTED]> w >> rote: >>> >>> >>>> On Apr 18, 9:36 pm, Ross Ridge <[EMAIL PROTECTED]> >>>> wrote: >>>>> Ross Ridge <[EMAIL PROTECTED]> said: >>>>>> If you have Python 2.5, here's a faster version: >>>>>> from struct import * >>>>>> unpack_i32be = Struct(">l").unpack >>>>>> def from3Bytes_ross2(s): >>>>>> return unpack_i32be(s + "\0")[0] >> 8 >>>>> Bob Greschke <[EMAIL PROTECTED]> wrote: >>>>>> That's not even intelligible. I wanna go back to COBOL. :) >>>>> It's the same as the previous version except that it "precompiles" >>>>> the struct.unpack() format string. It works similar to the way Python >>>>> handles regular expressions. >>>> I didn't know about the Struct class; pretty neat. It's amazing that >>>> this version without Psyco is as fast Bob's version with Psyco! Adding >>>> Psyco to it though makes it *slower*, not faster. So here's how I'd >>>> write it (if I wanted or had to stay in pure Python): >>>> try: import psyco >>>> except ImportError: >>>> from struct import Struct >>>> unpack_i32be = Struct(">l").unpack >>>> def from3Bytes(s): >>>> return unpack_i32be(s + "\0")[0] >> 8 >>>> else: >>>> def from3Bytes(s): >>>> Value = (ord(s[0])<<16) + (ord(s[1])<<8) + ord(s[2]) >>>> if Value >= 0x800000: >>>> Value -= 0x1000000 >>>> return Value >>>> psyco.bind(from3Bytes) >>>> HTH, >>>> George >>> I was able to get even faster pure-python version using array module: >>> >>> a = array.array('l', ''.join(('\0' + s[i:i+3] for i in xrange(0, >>> len(s), 3)))) >>> if sys.byteorder == 'little': >>> a.byteswap() >>> >>> It actually moves bytes around on C level. >>> >>> test code: >>> import struct >>> import array >>> import sys >>> >>> unpack_i32be = struct.Struct(">l").unpack >>> s = ''.join(struct.pack('>i', 1234567)[1:]*1000) >>> >>> def from3bytes_ord(s): >>> values = [] >>> for i in xrange(0, len(s), 3): >>> Value = (ord(s[i])<<16) | (ord(s[i+1])<<8) | ord(s[i+2]) >>> if Value >= 0x800000: >>> Value -= 0x1000000 >>> values.append(Value) >>> return values >>> >>> def from3bytes_struct(s): >>> return [unpack_i32be(s[i:i+3] + "\0")[0] >> 8 for i in xrange(0, >>> len(s), 3)] >>> >>> def from3bytes_array(s): >>> a = array.array('l', ''.join(('\0' + s[i:i+3] for i in xrange(0, >>> len(s), 3)))) >>> if sys.byteorder == 'little': >>> a.byteswap() >>> return a.tolist() >>> >>> from timeit import Timer >>> >>> t1 = Timer("from3bytes_ord(s)", "from __main__ import s, >>> from3bytes_ord") >>> t2 = Timer("from3bytes_struct(s)", "from __main__ import s, >>> from3bytes_struct") >>> t3 = Timer("from3bytes_array(s)", "from __main__ import s, >>> from3bytes_array") >>> >>> print 'ord:\t', t1.timeit(1000) >>> print 'struct:\t', t2.timeit(1000) >>> print 'array:\t', t3.timeit(1000) >>> >>> Output: >>> ord: 7.08213110884 >>> struct: 3.7689164405 >>> array: 2.62995268952 >>> >>> Inspired by Guido's essayhttp://www.python.org/doc/essays/list2str/ >> And even faster: >> a = array.array('i', '\0' + '\0'.join((s[i:i+3] for i in xrange(0, >> len(s), 3)))) >> if sys.byteorder == 'little': >> a.byteswap() >> >> I think it's a fastest possible implementation in pure python > > Geeze! :) How did struct get so fast? I'm guessing there have been > improvements since 2.3 (which is what I've been working on). I'm going > to be able to go back to my IBM PC XT pretty soon. :) > > Thanks! > Yes, Bob Ippolito spent quite a bit of time improving it at the Need for Speed sprint shortly before the 2.4 (?) release. It shows.
regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/ -- http://mail.python.org/mailman/listinfo/python-list