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