Bug 81093

Summary: lang/php4 - Slow serialize on FreeBSD
Product: Ports & Packages Reporter: Chatchawan Wongsiriprasert <cws>
Component: Individual Port(s)Assignee: Alex Dupre <ale>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: Latest   
Hardware: Any   
OS: Any   

Description Chatchawan Wongsiriprasert 2005-05-16 07:50:02 UTC
Serialize use a fix incremental value (SMART_STR_PREALLOC in
php_smart_ptr.h) to expand the serailized string. It better for serialize to use exponential incremential value to reduce number of realloc because
realloc is very slow on FreeBSD    

It took about 2 seconds to serialize 2MB array on FreeBSD. The same code run about 0.2 second on Linux

Fix: apply the patch http://freebie.miraclenet.co.th/tmp/patch-php_smart_str.h



#ifndef SMART_STR_PREALLOC
-#define SMART_STR_PREALLOC 128
+#define SMART_STR_PREALLOC 1024
+#endif
+
+#ifndef SMART_PTR_MAX_PREALLOC
+#define SMART_PTR_MAX_PREALLOC 1048576
 #endif

 #ifdef SMART_STR_USE_REALLOC
@@ -42,8 +46,11 @@
        if (!d->c) d->len = d->a = 0; \
        newlen = d->len + n; \
        if (newlen >= d->a) {\
-               d->c = SMART_STR_REALLOC(d->c, newlen + SMART_STR_PREALLOC + 1, what); \
-               d->a = newlen + SMART_STR_PREALLOC; \
+               size_t pre_alloc = newlen *2;\
+               if ( pre_alloc > SMART_PTR_MAX_PREALLOC ) { pre_alloc = SMART_PTR_MAX_PREALLOC; }\
+               else if ( pre_alloc < SMART_STR_PREALLOC) { pre_alloc = SMART_STR_PREALLOC; }\
+               d->c = SMART_STR_REALLOC(d->c, newlen + pre_alloc + 1, what); \
+               d->a = newlen + pre_alloc; \
        }\
 }--LxijQppuUXDx3v5bC2qjLw5DLEFVSs3hqPf5Pl1ROjKk0DwG
Content-Type: text/plain; name="file.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="file.diff"

--- ext/standard/php_smart_str.h.org    Wed Apr 16 16:12:37 2003
+++ ext/standard/php_smart_str.h        Wed Apr 20 14:17:21 2005
@@ -29,7 +29,11 @@
 #define smart_str_0(x) do { if ((x)->c) { (x)->c[(x)->len] = '\0'; } } while (0)
How-To-Repeat: The test code and data can be download at
http://freebie.miraclenet.co.th/tmp/test_serialize.tgz
Comment 1 Pav Lucistnik freebsd_committer freebsd_triage 2005-05-16 22:58:29 UTC
Responsible Changed
From-To: freebsd-ports-bugs->ale

Over to maintainer
Comment 2 dereckson 2009-07-07 07:12:43 UTC
On PHP 5, this is a slighty modified version of this code but the same principe.

Can't test http://freebie.miraclenet.co.th/tmp/test_serialize.tgz, 404 error.
Comment 3 Alex Dupre freebsd_committer freebsd_triage 2009-07-14 13:20:16 UTC
Can you try the following patch (for PHP5) and tell me the results (and 
which FreeBSD version you are using)?


--- ext/standard/php_smart_str.h.orig   2009-07-14 14:08:07.000000000 +0200
+++ ext/standard/php_smart_str.h        2009-07-14 14:08:12.000000000 +0200
@@ -30,12 +30,14 @@

  #define smart_str_0(x) do { 
                                          \
         if ((x)->c) { 
                                                  \
+               (x)->a = (x)->len; \
+               SMART_STR_DO_REALLOC(x, 0); \
                 (x)->c[(x)->len] = '\0'; 
                                          \
         } 
                                                                  \
  } while (0)

  #ifndef SMART_STR_PREALLOC
-#define SMART_STR_PREALLOC 128
+#define SMART_STR_PREALLOC 1048576
  #endif

  #ifndef SMART_STR_START_SIZE


-- 
Alex Dupre
Comment 4 Alex Dupre freebsd_committer freebsd_triage 2009-07-14 13:20:42 UTC
State Changed
From-To: open->feedback

Waiting for feedback.
Comment 5 Chatchawan Wongsiriprasert 2009-08-08 10:02:02 UTC
The problem is not exists anymore FreeBSD 7/PHP 5

The result without apply any patch to FreeBSD7/PHP5

OS         : FreeBSD 7.1-RELEASE  amd64
PHP Version:5.2.9
Serialize result length:9022301
Serialize time         :0.065906 second

Test code:

<?php
        $a = array();
        for($i = 0; $i < 1024; ++$i)
        {
                $test_ch = chr($i % 26+ord('A'));

                $a[] = array(
                                'id' => $i,
                                'ch1' => str_repeat($test_ch,255),
                                'ch2' =>
str_repeat(strtolower($test_ch),255),
                                'data3' => str_repeat('A',4096),
                                'data4' => str_repeat('B',4096),
                        );
        }

        $st = microtime_float();
        $str = serialize($a);
        $end = microtime_float();

        print "OS         :" . `/usr/bin/uname -rps` . "\n";
        print "PHP Version:" . phpversion() . "\n";
        print "Serialize result length:" . strlen($str) . "\n";
        print "Serialize time         :" . sprintf("%f second\n",$end-$st);
?>
<?php
function microtime_float()
{
   list($usec, $sec) = explode(" ", microtime());
   return ((float)$usec + (float)$sec);
}
?>
Comment 6 Alex Dupre freebsd_committer freebsd_triage 2009-12-01 11:34:57 UTC
State Changed
From-To: feedback->closed

Closed as submitter request.