Author: Antonio Cuni <anto.c...@gmail.com> Branch: faster-rstruct-2 Changeset: r91269:196fb3e1e9b3 Date: 2017-05-12 18:19 +0200 http://bitbucket.org/pypy/pypy/changeset/196fb3e1e9b3/
Log: finally! Add a fastpath for packing ints :) diff --git a/rpython/rlib/rstruct/standardfmttable.py b/rpython/rlib/rstruct/standardfmttable.py --- a/rpython/rlib/rstruct/standardfmttable.py +++ b/rpython/rlib/rstruct/standardfmttable.py @@ -14,9 +14,12 @@ from rpython.rlib.unroll import unrolling_iterable from rpython.rlib.buffer import StringBuffer from rpython.rlib import rarithmetic -from rpython.rlib.buffer import CannotRead +from rpython.rlib.buffer import CannotRead, CannotWrite from rpython.rtyper.lltypesystem import rffi +USE_FASTPATH = True # set to False by some tests +ALLOW_SLOWPATH = True # set to False by some tests + native_is_bigendian = struct.pack("=i", 1) == struct.pack(">i", 1) native_is_ieee754 = float.__getformat__('double').startswith('IEEE') @@ -65,6 +68,21 @@ fmtiter.advance(1) _pack_string(fmtiter, string, count-1) +@specialize.memo() +def pack_fastpath(TYPE): + @specialize.argtype(0) + def do_pack_fastpath(fmtiter, value): + size = rffi.sizeof(TYPE) + pos = fmtiter.pos + if (not USE_FASTPATH or + fmtiter.bigendian != native_is_bigendian or + pos % size != 0): + raise CannotWrite + # the following might raise CannotWrite and abort the fastpath + fmtiter.result.typed_write(TYPE, fmtiter.pos, value) + fmtiter.advance(size) + return do_pack_fastpath + def make_float_packer(size): def packer(fmtiter): fl = fmtiter.accept_float_arg() @@ -124,6 +142,7 @@ errormsg = "argument out of range for %d-byte%s integer format" % (size, plural) unroll_revrange_size = unrolling_iterable(range(size-1, -1, -1)) + TYPE = get_rffi_int_type(size, signed) def pack_int(fmtiter): method = getattr(fmtiter, accept_method) @@ -131,6 +150,14 @@ if not min <= value <= max: raise StructError(errormsg) # + try: + pack_fastpath(TYPE)(fmtiter, value) + return + except CannotWrite: + if not ALLOW_SLOWPATH: + # we enter here only in some tests + raise ValueError("fastpath not taken :(") + # pos = fmtiter.pos + size - 1 if fmtiter.bigendian: for i in unroll_revrange_size: @@ -148,9 +175,6 @@ # ____________________________________________________________ -USE_FASTPATH = True # set to False by some tests -ALLOW_SLOWPATH = True # set to False by some tests - @specialize.memo() def unpack_fastpath(TYPE): diff --git a/rpython/rlib/rstruct/test/test_pack.py b/rpython/rlib/rstruct/test/test_pack.py --- a/rpython/rlib/rstruct/test/test_pack.py +++ b/rpython/rlib/rstruct/test/test_pack.py @@ -1,4 +1,5 @@ import pytest +from rpython.rlib.rarithmetic import r_ulonglong from rpython.rlib.rstruct import standardfmttable, nativefmttable from rpython.rlib.mutbuffer import MutableStringBuffer import struct @@ -40,6 +41,23 @@ fmt_prefix = None fmttable = None + USE_FASTPATH = True + ALLOW_SLOWPATH = True + + def setup_method(self, meth): + standardfmttable.USE_FASTPATH = self.USE_FASTPATH + standardfmttable.ALLOW_SLOWPATH = self.ALLOW_SLOWPATH + + def teardown_method(self, meth): + standardfmttable.USE_FASTPATH = True + standardfmttable.ALLOW_SLOWPATH = True + + def teardown_method(self, meth): + if not hasattr(self.fmttable, 'USE_FASTPATH'): + return + self.fmttable.USE_FASTPATH = self.orig_use_fastpath + self.fmttable.ALLOW_SLOWPATH = self.orig_allow_slowpath + def mypack(self, fmt, value): size = struct.calcsize(fmt) fake_fmtiter = FakeFormatIter(self.bigendian, size, value) @@ -69,7 +87,7 @@ self.check("I", 0x81424344) self.check("q", 0x4142434445464748) self.check("q", -0x41B2B3B4B5B6B7B8) - self.check("Q", 0x8142434445464748) + self.check("Q", r_ulonglong(0x8142434445464748)) def test_pack_ieee(self): self.check('f', 123.456) @@ -107,12 +125,22 @@ fmt_prefix = '<' fmttable = standardfmttable.standard_fmttable +class TestPackLittleEndianSlowPath(TestPackLittleEndian): + USE_FASTPATH = False + class TestPackBigEndian(BaseTestPack): bigendian = True fmt_prefix = '>' fmttable = standardfmttable.standard_fmttable +class TestPackBigEndianSlowPath(TestPackBigEndian): + USE_FASTPATH = False + + class TestNative(BaseTestPack): + # native packing automatically use the proper endianess, so it should + # always take the fast path + ALLOW_SLOWPATH = False bigendian = nativefmttable.native_is_bigendian fmt_prefix = '@' fmttable = nativefmttable.native_fmttable _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit