Author: Antonio Cuni <[email protected]>
Branch: faster-rstruct
Changeset: r80785:7cf0a0cef3b5
Date: 2015-11-20 01:01 +0100
http://bitbucket.org/pypy/pypy/changeset/7cf0a0cef3b5/

Log:    add a fast-path to unpack_double, which reads directly from the
        input string instead of taking a slice. There are still some rough
        edges, but I commit this anyway so I can translate while I sleep :)

diff --git a/pypy/module/struct/formatiterator.py 
b/pypy/module/struct/formatiterator.py
--- a/pypy/module/struct/formatiterator.py
+++ b/pypy/module/struct/formatiterator.py
@@ -149,3 +149,17 @@
     @specialize.argtype(1)
     def appendobj(self, value):
         self.result_w.append(self.space.wrap(value))
+
+    def is_aligned(self, size):
+        return self.pos % size == 0
+
+    def get_buffer(self):
+        # XXX: if self.buf is something different that StringBuffer, this has
+        # the effect to copy the whole string at each unpack!
+        return self.buf.as_str()
+
+    def get_pos(self):
+        return self.pos
+
+    def advance(self, size):
+        self.read(size) # XXX, could avoid taking the slice
diff --git a/rpython/rlib/rstruct/nativefmttable.py 
b/rpython/rlib/rstruct/nativefmttable.py
--- a/rpython/rlib/rstruct/nativefmttable.py
+++ b/rpython/rlib/rstruct/nativefmttable.py
@@ -44,8 +44,16 @@
 
 @specialize.argtype(0)
 def unpack_double(fmtiter):
-    input = fmtiter.read(sizeof_double)
-    doubleval = str_storage_getitem(rffi.DOUBLE, input, 0)
+    if fmtiter.is_aligned(sizeof_double):
+        # fast path
+        input = fmtiter.get_buffer()
+        pos = fmtiter.get_pos()
+        doubleval = str_storage_getitem(rffi.DOUBLE, input, pos)
+        fmtiter.advance(sizeof_double)
+    else:
+        # slow path, take the slice
+        input = fmtiter.read(sizeof_double)
+        doubleval = str_storage_getitem(rffi.DOUBLE, input, 0)
     fmtiter.appendobj(doubleval)
 
 def pack_float(fmtiter):
diff --git a/rpython/rlib/rstruct/runpack.py b/rpython/rlib/rstruct/runpack.py
--- a/rpython/rlib/rstruct/runpack.py
+++ b/rpython/rlib/rstruct/runpack.py
@@ -38,6 +38,18 @@
 
         def appendobj(self, value):
             self.value = value
+
+        def is_aligned(self, size):
+            return self.mr.inputpos % size == 0
+
+        def get_buffer(self):
+            return self.mr.input
+
+        def get_pos(self):
+            return self.mr.inputpos
+
+        def advance(self, size):
+            self.read(size) # XXX, could avoid taking the slice
     ReaderForPos.__name__ = 'ReaderForPos%d' % pos
     return ReaderForPos
 
diff --git a/rpython/rlib/rstruct/test/test_runpack.py 
b/rpython/rlib/rstruct/test/test_runpack.py
--- a/rpython/rlib/rstruct/test/test_runpack.py
+++ b/rpython/rlib/rstruct/test/test_runpack.py
@@ -43,11 +43,9 @@
         """
         Check the 'd' and 'f' format characters on native packing.
         """
-        d_data = struct.pack("d", 12.34)
-        f_data = struct.pack("f", 12.34)
+        d_data = struct.pack("df", 12.34, 12.34)
         def fn():
-            d = runpack("@d", d_data)
-            f = runpack("@f", f_data)
+            d, f = runpack("@df", d_data)
             return d, f
         #
         res = self.interpret(fn, [])
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to