FAQ
Hi Brain,

I've committed your patch into all branches, because it not only improve
performance on x86_64, but also fixes a bug in x86 code.

Thank you very much.

Dmitry.
-------- Original Message --------
Subject: [PHP-DEV] PATCH: zend_alloc.c x86_64 optimization
Date: Wed, 28 Nov 2007 14:27:29 -0800
From: Brian Shire <shire@php.net>
To: internals@lists.php.net


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);

Search Discussions

  • Brian Shire at Dec 20, 2007 at 6:03 pm
    Looks great, thanks!

    -shire
    On Dec 20, 2007, at 5:22 AM, Dmitry Stogov wrote:

    Hi Brain,

    I've committed your patch into all branches, because it not only
    improve performance on x86_64, but also fixes a bug in x86 code.

    Thank you very much.

    Dmitry.
    -------- Original Message --------
    Subject: [PHP-DEV] PATCH: zend_alloc.c x86_64 optimization
    Date: Wed, 28 Nov 2007 14:27:29 -0800
    From: Brian Shire <shire@php.net>
    To: internals@lists.php.net
    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);

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupphp-internals @
categoriesphp
postedDec 20, '07 at 1:22p
activeDec 20, '07 at 6:03p
posts2
users2
websitephp.net

2 users in discussion

Dmitry Stogov: 1 post Brian Shire: 1 post

People

Translate

site design / logo © 2022 Grokbase