You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2010/01/30 02:48:15 UTC

svn commit: r904708 - in /lucene/lucy/trunk: core/Lucy/Object/ core/Lucy/Test/Object/ core/Lucy/Test/Util/ core/Lucy/Util/ perl/lib/Lucy/ perl/t/core/

Author: marvin
Date: Sat Jan 30 01:48:14 2010
New Revision: 904708

URL: http://svn.apache.org/viewvc?rev=904708&view=rev
Log:
Add Memory_oversize(), which consolidates strategies for incremental growth of
dynamic arrays within one, testable function.  (LUCY-97)

Added:
    lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.bp   (with props)
    lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.c   (with props)
    lucene/lucy/trunk/perl/t/core/039-memory.t   (with props)
Modified:
    lucene/lucy/trunk/core/Lucy/Object/BitVector.c
    lucene/lucy/trunk/core/Lucy/Object/ByteBuf.c
    lucene/lucy/trunk/core/Lucy/Object/CharBuf.c
    lucene/lucy/trunk/core/Lucy/Object/VArray.c
    lucene/lucy/trunk/core/Lucy/Test/Object/TestBitVector.c
    lucene/lucy/trunk/core/Lucy/Util/Memory.bp
    lucene/lucy/trunk/core/Lucy/Util/Memory.c
    lucene/lucy/trunk/perl/lib/Lucy/Test.pm

Modified: lucene/lucy/trunk/core/Lucy/Object/BitVector.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/BitVector.c?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/BitVector.c (original)
+++ lucene/lucy/trunk/core/Lucy/Object/BitVector.c Sat Jan 30 01:48:14 2010
@@ -5,12 +5,6 @@
 
 #include "Lucy/Object/BitVector.h"
 
-#define BITVEC_GROW(self, num) \
-    do { \
-        if (num >= self->cap) \
-            BitVec_Grow(self, num); \
-    } while (0)
-
 /* Shared subroutine for performing both OR and XOR ops.
  */
 #define DO_OR 1
@@ -108,18 +102,18 @@
         u32_t space = my_byte_size - evil_twin_byte_size;
         memset(self->bits + evil_twin_byte_size, 0, space);
     }
-    else {
-        BitVec_Grow(self, evil_twin->cap);
+    else if (my_byte_size < evil_twin_byte_size) {
+        BitVec_Grow(self, evil_twin->cap - 1);
     }
     memcpy(self->bits, evil_twin->bits, evil_twin_byte_size);
 }
 
 void
-BitVec_grow(BitVector *self, u32_t new_max) 
+BitVec_grow(BitVector *self, u32_t capacity) 
 {
-    if (new_max >= self->cap) {
+    if (capacity > self->cap) {
         const size_t old_byte_cap  = (size_t)ceil(self->cap / 8.0); 
-        const size_t new_byte_cap  = (size_t)ceil((new_max + 1) / 8.0); 
+        const size_t new_byte_cap  = (size_t)ceil((capacity + 1) / 8.0); 
         const size_t num_new_bytes = new_byte_cap - old_byte_cap;
 
         self->bits = (u8_t*)REALLOCATE(self->bits, new_byte_cap);
@@ -131,7 +125,10 @@
 void 
 BitVec_set(BitVector *self, u32_t tick) 
 {
-    BITVEC_GROW(self, tick);
+    if (tick >= self->cap) {
+        uint32_t new_cap = (uint32_t)Memory_oversize(tick + 1, 0);
+        BitVec_Grow(self, new_cap);
+    }
     NumUtil_u1set(self->bits, tick);
 }
 
@@ -257,7 +254,7 @@
     }
 
     /* Grow self if smaller than other, then calc pointers. */
-    BITVEC_GROW(self, max_cap);
+    if (max_cap > self->cap) { BitVec_Grow(self, max_cap); }
     bits_a        = self->bits;
     bits_b        = other->bits;
     byte_size     = ceil(min_cap / 8.0);
@@ -309,7 +306,10 @@
 void
 BitVec_flip(BitVector *self, u32_t tick) 
 {
-    BITVEC_GROW(self, tick);
+    if (tick >= self->cap) {
+        uint32_t new_cap = (uint32_t)Memory_oversize(tick + 1, 0);
+        BitVec_Grow(self, new_cap);
+    }
     NumUtil_u1flip(self->bits, tick);
 }
 
@@ -322,7 +322,7 @@
     /* Bail if there's nothing to flip. */
     if (!length) { return; }
 
-    BITVEC_GROW(self, last);
+    if (last >= self->cap) { BitVec_Grow(self, last + 1); }
 
     /* Flip partial bytes. */
     while (last % 8 != 0 && last > first) {

Modified: lucene/lucy/trunk/core/Lucy/Object/ByteBuf.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/ByteBuf.c?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/ByteBuf.c (original)
+++ lucene/lucy/trunk/core/Lucy/Object/ByteBuf.c Sat Jan 30 01:48:14 2010
@@ -15,9 +15,8 @@
 #include "Lucy/Store/OutStream.h"
 #include "Lucy/Util/Memory.h"
 
-/* Reallocate if necessary. */
-static INLINE void
-SI_maybe_grow(ByteBuf *self, size_t capacity);
+static void
+S_grow(ByteBuf *self, size_t size);
 
 ByteBuf*
 BB_new(size_t capacity) 
@@ -33,7 +32,7 @@
     self->buf   = NULL;
     self->size  = 0;
     self->cap   = 0;
-    SI_maybe_grow(self, amount);
+    S_grow(self, amount);
     return self;
 }
 
@@ -131,7 +130,7 @@
 static INLINE void
 SI_mimic_bytes(ByteBuf *self, const void *bytes, size_t size) 
 {
-    SI_maybe_grow(self, size);
+    if (size > self->cap) { S_grow(self, size); }
     memmove(self->buf, bytes, size);
     self->size = size;
 }
@@ -153,7 +152,9 @@
 SI_cat_bytes(ByteBuf *self, const void *bytes, size_t size) 
 {
     const size_t new_size = self->size + size;
-    SI_maybe_grow(self, new_size);
+    if (new_size > self->cap) { 
+        S_grow(self, Memory_oversize(new_size, sizeof(char))); 
+    }
     memcpy((self->buf + self->size), bytes, size);
     self->size = new_size;
 }
@@ -171,25 +172,24 @@
 }
 
 static void
-S_grow(ByteBuf *self, size_t capacity)
+S_grow(ByteBuf *self, size_t size)
 {
-    size_t bleedover = capacity % sizeof(i64_t);
-    size_t amount    = capacity + sizeof(i64_t) - bleedover;
-    self->buf = (char*)REALLOCATE(self->buf, amount);
-    self->cap = amount;
-}
-
-static INLINE void
-SI_maybe_grow(ByteBuf *self, size_t capacity) 
-{
-    /* Reallocate only if necessary. */
-    if (self->cap < capacity) { S_grow(self, capacity); }
+    if (size > self->cap) {
+        size_t amount    = size;
+        size_t remainder = amount % sizeof(int64_t);
+        if (remainder) {
+            amount += sizeof(int64_t);
+            amount -= remainder;
+        }
+        self->buf = (char*)REALLOCATE(self->buf, amount);
+        self->cap = amount;
+    }
 }
 
 char*
-BB_grow(ByteBuf *self, size_t capacity) 
+BB_grow(ByteBuf *self, size_t size) 
 {
-    SI_maybe_grow(self, capacity);
+    if (size > self->cap) { S_grow(self, size); }
     return self->buf;
 }
 
@@ -204,8 +204,9 @@
 BB_deserialize(ByteBuf *self, InStream *instream)
 {
     const size_t size = InStream_Read_C32(instream);
+    const size_t capacity = size ? size : sizeof(i64_t);
     self = self ? self : (ByteBuf*)VTable_Make_Obj(BYTEBUF);
-    SI_maybe_grow(self, size);
+    if (capacity > self->cap) { S_grow(self, capacity); }
     self->size = size;
     InStream_Read_Bytes(instream, self->buf, size);
     return self;

Modified: lucene/lucy/trunk/core/Lucy/Object/CharBuf.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/CharBuf.c?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/CharBuf.c (original)
+++ lucene/lucy/trunk/core/Lucy/Object/CharBuf.c Sat Jan 30 01:48:14 2010
@@ -21,10 +21,6 @@
 /* The end of the string (address of terminating NULL). */
 #define CBEND(self) ((self)->ptr + (self)->size)
 
-/* Reallocate if necessary. */
-static INLINE void
-SI_maybe_grow(CharBuf *self, size_t new_size);
-
 /* Maximum number of characters in a stringified 64-bit integer, including
  * minus sign if negative.
  */
@@ -145,21 +141,19 @@
     return (i32_t) hashvalue;
 }
 
-static INLINE void
-SI_maybe_grow(CharBuf *self, size_t new_size) 
+static void
+S_grow(CharBuf *self, size_t size)
 {
-    /* Bail out if the buffer's already at least as big as required. */
-    if (self->cap > new_size)
-        return;
-
-    self->ptr = (char*)REALLOCATE(self->ptr, new_size + 1);
-    self->cap = new_size + 1;
+    if (size >= self->cap) { 
+        self->cap = size + 1;
+        self->ptr = (char*)REALLOCATE(self->ptr, self->cap);
+    }
 }
 
 char*
-CB_grow(CharBuf *self, size_t new_size) 
+CB_grow(CharBuf *self, size_t size) 
 {
-    SI_maybe_grow(self, new_size);
+    if (size >= self->cap) { S_grow(self, size); }
     return self->ptr;
 }
 
@@ -357,9 +351,10 @@
 void
 CB_cat_char(CharBuf *self, u32_t code_point)
 {
-    const size_t MIN_SAFE_ROOM = 4 + 1;
-    if (self->size + MIN_SAFE_ROOM > self->cap) {
-        SI_maybe_grow(self, self->size + 10);
+    const size_t MAX_UTF8_BYTES = 4;
+    if (self->size + MAX_UTF8_BYTES >= self->cap) { 
+        S_grow(self, Memory_oversize(self->size + MAX_UTF8_BYTES, 
+            sizeof(char)));
     }
     self->size += StrHelp_encode_utf8_char(code_point, (u8_t*)CBEND(self));
     *CBEND(self) = '\0';
@@ -469,7 +464,7 @@
 {
     size_t size = InStream_Read_C32(instream);
     self = self ? self : (CharBuf*)VTable_Make_Obj(CHARBUF);
-    SI_maybe_grow(self, size);
+    if (size >= self->cap) { S_grow(self, size); }
     InStream_Read_Bytes(instream, self->ptr, size);
     self->size = size;
     self->ptr[size] = '\0';
@@ -482,9 +477,10 @@
 void
 CB_mimic_str(CharBuf *self, const char* ptr, size_t size) 
 {
-    if (!StrHelp_utf8_valid(ptr, size))
+    if (!StrHelp_utf8_valid(ptr, size)) {
         S_die_invalid_utf8(ptr, size);
-    SI_maybe_grow(self, size);
+    }
+    if (size >= self->cap) { S_grow(self, size); }
     memmove(self->ptr, ptr, size);
     self->size = size;
     self->ptr[size] = '\0';
@@ -494,7 +490,7 @@
 CB_mimic(CharBuf *self, Obj *other)
 {
     CharBuf *evil_twin = (CharBuf*)CERTIFY(other, CHARBUF);
-    SI_maybe_grow(self, evil_twin->size);
+    if (evil_twin->size >= self->cap) { S_grow(self, evil_twin->size); }
     memmove(self->ptr, evil_twin->ptr, evil_twin->size);
     self->size = evil_twin->size;
     self->ptr[evil_twin->size] = '\0';
@@ -512,7 +508,10 @@
 CB_cat_trusted_str(CharBuf *self, const char* ptr, size_t size) 
 {
     const size_t new_size = self->size + size;
-    SI_maybe_grow(self, new_size);
+    if (new_size >= self->cap) { 
+        size_t amount = Memory_oversize(new_size, sizeof(char));
+        S_grow(self, amount); 
+    }
     memcpy((self->ptr + self->size), ptr, size);
     self->size = new_size;
     self->ptr[new_size] = '\0';
@@ -522,7 +521,10 @@
 CB_cat(CharBuf *self, const CharBuf *other) 
 {
     const size_t new_size = self->size + other->size;
-    SI_maybe_grow(self, new_size);
+    if (new_size >= self->cap) { 
+        size_t amount = Memory_oversize(new_size, sizeof(char));
+        S_grow(self, amount); 
+    }
     memcpy((self->ptr + self->size), other->ptr, other->size);
     self->size = new_size;
     self->ptr[new_size] = '\0';

Modified: lucene/lucy/trunk/core/Lucy/Object/VArray.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/VArray.c?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/VArray.c (original)
+++ lucene/lucy/trunk/core/Lucy/Object/VArray.c Sat Jan 30 01:48:14 2010
@@ -14,13 +14,6 @@
 #include "Lucy/Store/InStream.h"
 #include "Lucy/Store/OutStream.h"
 
-#define MAYBE_GROW(_self, _new_size) \
-    do { \
-        if ((_self)->cap < _new_size) \
-            VA_grow(_self, _new_size); \
-    } while (0)
-
-
 VArray*
 VA_new(u32_t capacity) 
 {
@@ -171,7 +164,9 @@
 void
 VA_push(VArray *self, Obj *element) 
 {
-    MAYBE_GROW(self, self->size + 1);
+    if (self->size == self->cap) { 
+        VA_Grow(self, Memory_oversize(self->size + 1, sizeof(Obj*)));
+    }
     self->elems[ self->size ] = element;
     self->size++;
 }
@@ -181,14 +176,17 @@
 {
     u32_t i;
     u32_t tick = self->size;
-    MAYBE_GROW(self, self->size + other->size);
+    u32_t new_size = self->size + other->size;
+    if (new_size > self->cap) { 
+        VA_Grow(self, Memory_oversize(new_size, sizeof(Obj*))); 
+    }
     for (i = 0; i < other->size; i++, tick++) {
         Obj *elem = VA_Fetch(other, i);
         if (elem != NULL) {
             self->elems[tick] = INCREF(elem);
         }
     }
-    self->size += other->size;
+    self->size = new_size;
 }
 
 Obj*
@@ -203,7 +201,9 @@
 void
 VA_unshift(VArray *self, Obj *elem) 
 {
-    MAYBE_GROW(self, self->size + 1);
+    if (self->size == self->cap) { 
+        VA_Grow(self, Memory_oversize(self->size + 1, sizeof(Obj*)));
+    }
     memmove(self->elems + 1, self->elems, self->size * sizeof(Obj*));
     self->elems[0] = elem;
     self->size++;
@@ -236,20 +236,20 @@
 }
 
 void
-VA_store(VArray *self, u32_t num, Obj *elem) 
+VA_store(VArray *self, u32_t tick, Obj *elem) 
 {
-    MAYBE_GROW(self, num + 1);
-    if (num < self->size) { DECREF(self->elems[num]); }
-    else { self->size = num + 1; }
-    self->elems[num] = elem;
+    if (tick >= self->cap) {
+        VA_Grow(self, Memory_oversize(tick + 1, sizeof(Obj*))); 
+    }
+    if (tick < self->size) { DECREF(self->elems[tick]); }
+    else                   { self->size = tick + 1; }
+    self->elems[tick] = elem;
 }
 
 void
 VA_grow(VArray *self, u32_t capacity) 
 {
     if (capacity > self->cap) {
-        /* Add an extra 10%. */
-        capacity += capacity / 10;
         self->elems = (Obj**)REALLOCATE(self->elems, capacity * sizeof(Obj*)); 
         self->cap   = capacity;
         memset(self->elems + self->size, 0,

Modified: lucene/lucy/trunk/core/Lucy/Test/Object/TestBitVector.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Test/Object/TestBitVector.c?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Test/Object/TestBitVector.c (original)
+++ lucene/lucy/trunk/core/Lucy/Test/Object/TestBitVector.c Sat Jan 30 01:48:14 2010
@@ -437,10 +437,9 @@
 void
 TestBitVector_run_tests()
 {
-    TestBatch   *batch     = TestBatch_new(1029);
+    TestBatch *batch = TestBatch_new(1029);
 
     TestBatch_Plan(batch);
-
     test_Set_and_Get(batch);
     test_Flip(batch);
     test_Flip_Block_ascending(batch);

Added: lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.bp?rev=904708&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.bp (added)
+++ lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.bp Sat Jan 30 01:48:14 2010
@@ -0,0 +1,13 @@
+parcel Lucy;
+
+inert class Lucy::Test::Util::TestMemory {
+    inert void
+    run_tests();
+}
+
+/* Copyright 2005-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.bp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.c?rev=904708&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.c (added)
+++ lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.c Sat Jan 30 01:48:14 2010
@@ -0,0 +1,107 @@
+#define C_LUCY_TESTMEMORYPOOL
+#define C_LUCY_MEMORYPOOL
+#include "Lucy/Util/ToolSet.h"
+
+#include "Lucy/Test.h"
+#include "Lucy/Test/Util/TestMemory.h"
+
+static void
+test_oversize__growth_rate(TestBatch *batch)
+{
+    bool_t   success             = true;
+    uint64_t size                = 0;
+    double   growth_count        = 0;
+    double   average_growth_rate = 0.0;
+
+    while (size < SIZE_MAX) {
+        uint64_t next_size = Memory_oversize(size + 1, sizeof(void*));
+        if (next_size < size) {
+            success = false;
+            FAIL(batch, "Asked for %" I64P ", got smaller amount %" I64P,
+                size + 1, next_size);
+            break;
+        }
+        if (size > 0) {
+            growth_count += 1;
+            double growth_rate = (double)next_size / (double)size;
+            double sum = growth_rate + (growth_count - 1) * average_growth_rate;
+            average_growth_rate = sum / growth_count;
+            if (average_growth_rate < 1.1) {
+                FAIL(batch, "Average growth rate dropped below 1.1x: %f", 
+                    average_growth_rate);
+                success = false;
+                break;
+            }
+        }
+        size = next_size;
+    }
+    ASSERT_TRUE(batch, growth_count > 0, "Grew %f times", growth_count);
+    if (success) {
+        ASSERT_TRUE(batch, average_growth_rate > 1.1, 
+            "Growth rate of oversize() averages above 1.1: %.3f",
+            average_growth_rate);
+    }
+
+    for (int minimum = 1; minimum < 8; minimum++) {
+        uint64_t next_size = Memory_oversize(minimum, sizeof(void*));
+        double growth_rate = (double)next_size / (double)minimum;
+        ASSERT_TRUE(batch, growth_rate > 1.2, 
+            "Growth rate is higher for smaller arrays (%d, %.3f)", minimum,
+            growth_rate);
+    }
+}
+
+static void
+test_oversize__ceiling(TestBatch *batch)
+{
+    for (int width = 0; width < 10; width++) {
+        size_t size = Memory_oversize(SIZE_MAX, width);
+        ASSERT_TRUE(batch, size == SIZE_MAX, 
+            "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
+        size = Memory_oversize(SIZE_MAX - 1, width);
+        ASSERT_TRUE(batch, size == SIZE_MAX, 
+            "Memory_oversize hits ceiling at SIZE_MAX (width %d)", width);
+    }
+}
+
+static void
+test_oversize__rounding(TestBatch *batch)
+{
+    bool_t success = true;
+    int widths[] = { 1, 2, 4, 0 };
+
+    for (int width_tick = 0; widths[width_tick] != 0; width_tick++) {
+        int width = widths[width_tick];
+        for (int i = 0; i < 25; i++) { 
+            size_t size = Memory_oversize(i, width);
+            size_t bytes = size * width;
+            if (bytes % sizeof(void*) != 0) {
+                FAIL(batch, "Rounding failure for %d, width %d",
+                    i, width);
+                success = false;
+                return;
+            }
+        }
+    }
+    PASS(batch, "Round allocations up to the size of a pointer");
+}
+
+void
+TestMemory_run_tests()
+{
+    TestBatch *batch = TestBatch_new(30);
+
+    TestBatch_Plan(batch);
+    test_oversize__growth_rate(batch);
+    test_oversize__ceiling(batch);
+    test_oversize__rounding(batch);
+
+    DECREF(batch);
+}
+
+/* Copyright 2005-2010 Marvin Humphrey
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * under the same terms as Perl itself.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Test/Util/TestMemory.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: lucene/lucy/trunk/core/Lucy/Util/Memory.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Util/Memory.bp?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Util/Memory.bp (original)
+++ lucene/lucy/trunk/core/Lucy/Util/Memory.bp Sat Jan 30 01:48:14 2010
@@ -26,6 +26,16 @@
      */
     inert void
     wrapped_free(void *ptr);
+
+    /** Provide a number which is somewhat larger than the supplied number, so
+     * that incremental array growth does not trigger pathological
+     * reallocation.
+     * 
+     * @param minimum The minimum number of array elements.
+     * @param width The size of each array element in bytes.
+     */
+    inert size_t 
+    oversize(size_t minimum, size_t width);
 }
 
 __C__

Modified: lucene/lucy/trunk/core/Lucy/Util/Memory.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Util/Memory.c?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Util/Memory.c (original)
+++ lucene/lucy/trunk/core/Lucy/Util/Memory.c Sat Jan 30 01:48:14 2010
@@ -43,6 +43,47 @@
     free(ptr);
 }
 
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif
+
+size_t
+lucy_Memory_oversize(size_t minimum, size_t width)
+{
+    /* For larger arrays, grow by an excess of 1/8; grow faster when the array
+     * is small. */
+    size_t extra = minimum / 8;
+    if (extra < 3) {
+        extra = 3;
+    }
+    size_t amount = minimum + extra;
+
+    /* Detect wraparound and return SIZE_MAX instead. */
+    if (amount + 7 < minimum) { 
+        return SIZE_MAX;
+    }
+
+    /* Round up for small widths so that the number of bytes requested will be
+     * a multiple of the machine's word size. */
+    if (sizeof(size_t) == 8) { // 64-bit
+        switch(width) {
+        case 1:  amount = (amount + 7) & CHY_I64_C(0xFFFFFFFFFFFFFFF8); break;
+        case 2:  amount = (amount + 3) & CHY_I64_C(0xFFFFFFFFFFFFFFFC); break;
+        case 4:  amount = (amount + 1) & CHY_I64_C(0xFFFFFFFFFFFFFFFE); break;
+        default: break;
+        }
+    }
+    else { // 32-bit
+        switch(width) {
+        case 1:  amount = (amount + 3) & ((size_t)0xFFFFFFFC); break;
+        case 2:  amount = (amount + 1) & ((size_t)0xFFFFFFFE); break;
+        default: break;
+        }
+    }
+
+    return amount;
+}
+
 /* Copyright 2009 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");

Modified: lucene/lucy/trunk/perl/lib/Lucy/Test.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/lib/Lucy/Test.pm?rev=904708&r1=904707&r2=904708&view=diff
==============================================================================
--- lucene/lucy/trunk/perl/lib/Lucy/Test.pm (original)
+++ lucene/lucy/trunk/perl/lib/Lucy/Test.pm Sat Jan 30 01:48:14 2010
@@ -96,6 +96,9 @@
     else if (strEQ(package, "TestJson")) {
         lucy_TestJson_run_tests();
     }
+    else if (strEQ(package, "TestMemory")) {
+        lucy_TestMemory_run_tests();
+    }
     else if (strEQ(package, "TestNumberUtils")) {
         lucy_TestNumUtil_run_tests();
     }

Added: lucene/lucy/trunk/perl/t/core/039-memory.t
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/t/core/039-memory.t?rev=904708&view=auto
==============================================================================
--- lucene/lucy/trunk/perl/t/core/039-memory.t (added)
+++ lucene/lucy/trunk/perl/t/core/039-memory.t Sat Jan 30 01:48:14 2010
@@ -0,0 +1,6 @@
+use strict;
+use warnings;
+
+use Lucy::Test;
+Lucy::Test::run_tests("TestMemory");
+

Propchange: lucene/lucy/trunk/perl/t/core/039-memory.t
------------------------------------------------------------------------------
    svn:eol-style = native