[pypy-commit] pypy struct-double: a branch to speedup struct.pack('d', float). currently not working.

alex_gaynor noreply at buildbot.pypy.org
Sat Mar 3 18:43:10 CET 2012


Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch: struct-double
Changeset: r53142:c864362c97b7
Date: 2012-03-03 12:42 -0500
http://bitbucket.org/pypy/pypy/changeset/c864362c97b7/

Log:	a branch to speedup struct.pack('d', float). currently not working.

diff --git a/pypy/rlib/rstring.py b/pypy/rlib/rstring.py
--- a/pypy/rlib/rstring.py
+++ b/pypy/rlib/rstring.py
@@ -2,10 +2,12 @@
 """
 
 from pypy.annotation.model import (SomeObject, SomeString, s_None, SomeChar,
-    SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString, SomePtr, SomePBC)
+    SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString, SomePtr, SomePBC,
+    SomeFloat)
 from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rpython.lltypesystem import lltype
 from pypy.tool.pairtype import pair, pairtype
-from pypy.rpython.extregistry import ExtRegistryEntry
 
 
 # -------------- public API for string functions -----------------------
@@ -94,6 +96,24 @@
 class StringBuilder(AbstractStringBuilder):
     tp = str
 
+    def append_float(self, f):
+        import struct
+        from pypy.rpython.lltypesystem import rffi
+
+        T = lltype.typeOf(f)
+        if T == lltype.Float:
+            fmt = "d"
+        elif T == lltype.SingleFloat:
+            fmt = "f"
+        else:
+            raise TypeError("this takes only float and r_singlefloat")
+
+        size = rffi.sizeof(T)
+        self._grow(size)
+
+        self.l.append(struct.pack(fmt, f))
+
+
 class UnicodeBuilder(AbstractStringBuilder):
     tp = unicode
 
@@ -125,6 +145,10 @@
         assert isinstance(s_size, SomeInteger)
         return s_None
 
+    def method_append_float(self, f):
+        assert isinstance(f, SomeFloat)
+        return s_None
+
     def method_getlength(self):
         return SomeInteger(nonneg=True)
 
diff --git a/pypy/rlib/test/test_rstring.py b/pypy/rlib/test/test_rstring.py
--- a/pypy/rlib/test/test_rstring.py
+++ b/pypy/rlib/test/test_rstring.py
@@ -1,7 +1,9 @@
 import sys
 
+from pypy.rlib.rarithmetic import r_singlefloat
 from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit
 
+
 def test_split():
     assert split("", 'x') == ['']
     assert split("a", "a", 1) == ['', '']
@@ -33,6 +35,20 @@
     s.append_multiple_char('d', 4)
     assert s.build() == "aabcabdddd"
 
+    s = StringBuilder()
+    s.append("a")
+    s.append_float(3.0)
+    s.append("a")
+    assert s.getlength() == 10
+    assert s.build() == "a\x00\x00\x00\x00\x00\x00\x08 at a"
+
+    s = StringBuilder()
+    s.append("c")
+    s.append_float(r_singlefloat(2.0))
+    s.append("c")
+    assert s.getlength() == 6
+    assert s.build() == "c\x00\x00\x00 at c"
+
 def test_unicode_builder():
     s = UnicodeBuilder()
     s.append(u'a')
@@ -42,4 +58,4 @@
     s.append_multiple_char(u'd', 4)
     assert s.build() == 'aabcbdddd'
     assert isinstance(s.build(), unicode)
-        
+
diff --git a/pypy/rpython/lltypesystem/rbuilder.py b/pypy/rpython/lltypesystem/rbuilder.py
--- a/pypy/rpython/lltypesystem/rbuilder.py
+++ b/pypy/rpython/lltypesystem/rbuilder.py
@@ -3,7 +3,7 @@
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.annlowlevel import llstr
 from pypy.rpython.rptr import PtrRepr
-from pypy.rpython.lltypesystem import lltype, rstr
+from pypy.rpython.lltypesystem import lltype, rffi, rstr
 from pypy.rpython.lltypesystem.lltype import staticAdtMethod, nullptr
 from pypy.rpython.lltypesystem.rstr import (STR, UNICODE, char_repr,
     string_repr, unichar_repr, unicode_repr)
@@ -51,6 +51,8 @@
                                  ('buf', lltype.Ptr(UNICODE)),
                               adtmeths={'grow':staticAdtMethod(unicodebuilder_grow)})
 
+FLOAT_ARRAY = lltype.Ptr(lltype.Array(lltype.Float))
+
 MAX = 16*1024*1024
 
 class BaseStringBuilderRepr(AbstractStringBuilderRepr):
@@ -116,6 +118,17 @@
         ll_builder.used = used
 
     @staticmethod
+    def ll_append_float(ll_builder, f):
+        used = ll_builder.used
+        T = lltype.typeOf(f)
+        size = rffi.sizeof(T)
+        if used + size > ll_builder.allocated:
+            ll_builder.grow(ll_builder, size)
+
+        rffi.cast(FLOAT_ARRAY, lltype.direct_ptradd(ll_builder.buf.chars, used))[0] = f
+        ll_builder.used += size
+
+    @staticmethod
     def ll_getlength(ll_builder):
         return ll_builder.used
 
diff --git a/pypy/rpython/rbuilder.py b/pypy/rpython/rbuilder.py
--- a/pypy/rpython/rbuilder.py
+++ b/pypy/rpython/rbuilder.py
@@ -1,8 +1,8 @@
+from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint
+from pypy.rlib.rstring import INIT_SIZE
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.rmodel import Repr
 
-from pypy.rpython.rmodel import Repr
-from pypy.rpython.lltypesystem import lltype
-from pypy.rlib.rstring import INIT_SIZE
-from pypy.annotation.model import SomeChar, SomeUnicodeCodePoint
 
 class AbstractStringBuilderRepr(Repr):
     def rtyper_new(self, hop):
@@ -39,6 +39,11 @@
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll_append_charpsize, *vlist)
 
+    def rtype_method_append_float(self, hop):
+        vlist = hop.inputargs(self, lltype.Float)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll_append_float, *vlist)
+
     def rtype_method_getlength(self, hop):
         vlist = hop.inputargs(self)
         hop.exception_cannot_occur()
@@ -53,7 +58,7 @@
         vlist = hop.inputargs(self)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll_is_true, *vlist)
-        
+
     def convert_const(self, value):
         if not value is None:
             raise TypeError("Prebuilt builedrs that are not none unsupported")
diff --git a/pypy/rpython/test/test_rbuilder.py b/pypy/rpython/test/test_rbuilder.py
--- a/pypy/rpython/test/test_rbuilder.py
+++ b/pypy/rpython/test/test_rbuilder.py
@@ -90,7 +90,7 @@
             if s:
                 s.append("3")
             return bool(s)
-        
+
         def func(i):
             if i:
                 s = StringBuilder()
@@ -107,7 +107,7 @@
             if s:
                 s.append(u"3")
             return bool(s)
-        
+
         def func(i):
             if i:
                 s = UnicodeBuilder()
@@ -119,6 +119,19 @@
         res = self.interpret(func, [1])
         assert res
 
+    def test_append_float(self):
+        def func(d):
+            s = StringBuilder()
+            s.append("abc")
+            s.append_float(d)
+            s.append("abc")
+            return s.build()
+
+        res = self.ll_to_string(self.interpret(func, [3.0]))
+        assert res == "abc\x00\x00\x00\x00\x00\x00\x08 at abc"
+
+        res = self.ll_to_string(self.interpret(func, [r_singlefloat(2.0)]))
+        assert res == "abc\x00\x00\x00 at abc"
 
 class TestLLtype(BaseTestStringBuilder, LLRtypeMixin):
     pass


More information about the pypy-commit mailing list