[svn:parrot] r47512 - in trunk: src/pmc t/pmc

NotFound at svn.parrot.org NotFound at svn.parrot.org
Wed Jun 9 14:48:57 UTC 2010


Author: NotFound
Date: Wed Jun  9 14:48:57 2010
New Revision: 47512
URL: https://trac.parrot.org/parrot/changeset/47512

Log:
avoid excesive reallocations when grown a ByteBuffer byte by byte, add a test to exercise that, and fixes a cast

Modified:
   trunk/src/pmc/bytebuffer.pmc
   trunk/t/pmc/bytebuffer.t

Modified: trunk/src/pmc/bytebuffer.pmc
==============================================================================
--- trunk/src/pmc/bytebuffer.pmc	Wed Jun  9 14:24:07 2010	(r47511)
+++ trunk/src/pmc/bytebuffer.pmc	Wed Jun  9 14:48:57 2010	(r47512)
@@ -28,9 +28,11 @@
         __attribute__nonnull__(1)
         __attribute__nonnull__(2);
 
+static INTVAL grow_to(INTVAL position);
 #define ASSERT_ARGS_build_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
        PARROT_ASSERT_ARG(interp) \
     , PARROT_ASSERT_ARG(content))
+#define ASSERT_ARGS_grow_to __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 /* HEADERIZER END: static */
 
@@ -173,7 +175,7 @@
 
         GET_ATTR_allocated_size(INTERP, SELF, allocated_size);
         if (position >= allocated_size) {
-            INTVAL newsize = position + 1;
+            INTVAL newsize = grow_to(position);
             if (allocated_size == 0) {
                 INTVAL copysize = newsize;
                 STRING * source;
@@ -271,6 +273,11 @@
 
 =over 4
 
+=item C<static INTVAL grow_to(INTVAL position)>
+
+Calculate new size enough for using position and with some margin to
+decrease the number of reallocations.
+
 =item C<static STRING * build_string(PARROT_INTERP, const unsigned char
 *content, INTVAL size, const CHARSET *charset, const ENCODING *encoding)>
 
@@ -280,6 +287,17 @@
 
 */
 
+static INTVAL
+grow_to(INTVAL position)
+{
+    const UINTVAL blocksize = 2048;
+    UINTVAL minsize = position + 1;
+    return (INTVAL) (minsize < 64 ? 64 :
+           minsize < 256 ? 256 :
+           minsize < 1024 ? 1024 :
+           ((minsize + blocksize - 1) / blocksize) * blocksize);
+}
+
 PARROT_CANNOT_RETURN_NULL
 static STRING *
 build_string(PARROT_INTERP, ARGIN(const unsigned char *content),
@@ -295,7 +313,7 @@
     if (encoding == NULL)
         Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_ENCODING,
                 "Invalid encoding");
-    result = Parrot_str_new_init(interp, (char *)content, size, encoding, charset, 0);
+    result = Parrot_str_new_init(interp, (const char *)content, size, encoding, charset, 0);
     if (!CHARSET_VALIDATE(interp, result))
         Parrot_ex_throw_from_c_args(interp, NULL,
                 EXCEPTION_INVALID_STRING_REPRESENTATION,

Modified: trunk/t/pmc/bytebuffer.t
==============================================================================
--- trunk/t/pmc/bytebuffer.t	Wed Jun  9 14:24:07 2010	(r47511)
+++ trunk/t/pmc/bytebuffer.t	Wed Jun  9 14:48:57 2010	(r47512)
@@ -16,14 +16,17 @@
 
 =cut
 
+.include 'iglobals.pasm'
+
 .sub 'main' :main
     .include 'test_more.pir'
-    plan(17)
+    plan(18)
 
     test_init()
     test_set_string()
     test_set_byte()
     test_get_string()
+    test_alloc()
 .end
 
 .sub test_init
@@ -122,6 +125,63 @@
     is(n, 0xD1, "getting utf8 from buffer gives correct codepoint")
 .end
 
+.sub test_alloc
+    # Exercise buffer reallocation building a utf16 string with the
+    # codepoints 32-8192
+    .local pmc bb
+    .local int i, big, pos, b0, b1, c
+
+    # Get endianess to set the bytes in the appropiate order.
+    # *** XXX *** Need report from big endian platforms.
+    $P0 = getinterp
+    $P0 = $P0[.IGLOBALS_CONFIG_HASH]
+    big = $P0['bigendian']
+
+    bb = new ['ByteBuffer']
+    pos = 0
+    i = 32
+loopset:
+    b0 = div i, 256
+    b1 = mod i, 256
+    if big goto setbig
+    bb[pos] = b1
+    inc pos
+    bb[pos] = b0
+    inc pos
+    goto setdone
+setbig:
+    bb[pos] = b0
+    inc pos
+    bb[pos] = b1
+    inc pos
+setdone:
+    inc i
+    if i < 8192 goto loopset
+
+    .local string s
+    s = bb.'get_string'('unicode', 'utf16')
+
+    # Check string size
+    i = length s
+    if i != 8160 goto failed
+
+    # Check string content
+    i = 32
+    pos = 0
+loopcheck:
+    c = ord s, pos
+    if c != i goto failed
+    inc pos
+    inc i
+    if i < 8192 goto loopcheck
+    ok(1, "reallocation")
+    goto end
+failed:
+    say i
+    ok(0, "reallocation")
+end:
+.end
+
 # Local Variables:
 #   mode: pir
 #   fill-column: 100


More information about the parrot-commits mailing list