[pypy-commit] pypy faster-rstruct-2: finally! Add a fastpath for packing ints :)
antocuni
pypy.commits at gmail.com
Fri May 12 12:22:09 EDT 2017
Author: Antonio Cuni <anto.cuni at 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)
+ at 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
More information about the pypy-commit
mailing list