I noticed that there where some x86_64 assembly optimizations missing from Zend/zend_alloc.c, it only accounts for i386. The following patch should add x86_64 support (I don't have karma for Zend of course, patch is against 5.2.5), I've included a bench mark with a simple test script to test out memory allocation. I'd be interested in getting feedback on this and knowing what other's results are. Sorry for the custom micro-bench but zend_bench.php did show small gains, but they where extremely small to really show anything.

A note on the i386 assembly, I had to add the following '&' char to make sure the input/outputs are using different registers. Lack of this had caused some serious memory corruption on my system with -O2 so I'm guessing it might be appropriate to do the same on the i386 code as well, but I've left that out of this patch, perhaps someone with some assembler experience can verify this is correct?

-                                       : "=a"(res), "=d" (overflow)
+                                       : "=&a"(res), "=&d" (overflow)


Thanks,

-shire



<?php
$start = microtime(true);
for($i=0; $i< 1000000; $i++) {
  $x[$i] = 'xxxxx';
}
$stop = microtime(true);
print ($stop-$start)."\n";
?>




php-5.2.5
-----------
        no-asm          asm             delta
-----------------------------------------------------
Run1    0.926729918     0.767436981     -0.159292936
Run2    0.920269966     0.768045902     -0.152224064
Run3    0.918609858     0.758006096     -0.160603762
Total   2.765609741     2.293488979     -0.472120762
Percentage:                             -17.07%




Index: Zend/zend_alloc.c
===================================================================
--- Zend/zend_alloc.c   (revision 69567)
+++ Zend/zend_alloc.c   (working copy)
@@ -656,6 +656,11 @@

        __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm"  (_size));
        return n;
+#elif defined(__GNUC__) && defined(__x86_64__)
+       unsigned long n;
+
+       __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm" (_size));
+       return (unsigned int)n;
 #elif defined(_MSC_VER) && defined(_M_IX86)
        __asm {
                bsr eax, _size
@@ -677,6 +682,11 @@

        __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm"  (_size));
        return n;
+#elif defined(__GNUC__) && defined(__x86_64__)
+       unsigned long n;
+
+       __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm" (_size));
+  return (unsigned int)n;
 #elif defined(_MSC_VER) && defined(_M_IX86)
        __asm {
                bsf eax, _size
@@ -2309,18 +2319,30 @@
return _zend_mm_block_size(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
 }

-#if defined(__GNUC__) && defined(i386)
+#if defined(__GNUC__) && (defined(i386) || defined(__x86_64__))

static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
 {
        size_t res = nmemb;
-       unsigned long overflow ;
+       unsigned long overflow = 0;

-       __asm__ ("mull %3\n\taddl %4,%0\n\tadcl $0,%1"
+#if defined(i386)
+       __asm__ (       "mull %3    \n\t"
+                                               "addl %4,%0 \n\t"
+                                               "adcl $0,%1 \n\t"
             : "=a"(res), "=d" (overflow)
             : "%0"(res),
               "rm"(size),
               "rm"(offset));
+#else /* __x86_64__ */
+       __asm__ (       "mulq %3     \n\t"
+                                               "addq %4,%0  \n\t"
+                                               "adcq $0,%1  \n\t"
+                                       : "=&a"(res), "=&d" (overflow)
+                                       : "%0"(res),
+                                               "rm"(size),
+                                               "rm"(offset) );
+#endif
        
        if (UNEXPECTED(overflow)) {
zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu * %zu + %zu)", nmemb, size, offset);

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to