Re: Speedup usages of pg_*toa() functions - Mailing list pgsql-hackers

From Ranier Vilela
Subject Re: Speedup usages of pg_*toa() functions
Date
Msg-id CAEudQAoKAZ1GNNb_wkKmYTqvbkbYEHP97OhOW-Hi_1kMpmg3+g@mail.gmail.com
Whole thread Raw
In response to Re: Speedup usages of pg_*toa() functions  (Andrew Gierth <andrew@tao11.riddles.org.uk>)
Responses Re: Speedup usages of pg_*toa() functions
List pgsql-hackers
Em ter., 9 de jun. de 2020 às 13:01, Andrew Gierth <andrew@tao11.riddles.org.uk> escreveu:
>>>>> "Ranier" == Ranier Vilela <ranier.vf@gmail.com> writes:

 Ranier> Written like that, wouldn't it get better?

 Ranier> int
 Ranier> pg_lltoa(int64 value, char *a)
 Ranier> {
 Ranier>     if (value < 0)
 Ranier>     {
 Ranier>         int         len = 0;
 Ranier>         uint64      uvalue = (uint64) 0 - uvalue;
 Ranier>         a[len++] = '-';
 Ranier>         len += pg_ulltoa_n(uvalue, a + len);
 Ranier>         a[len] = '\0';
 Ranier>         return len;
 Ranier>     }
 Ranier>     else
 Ranier>         return pg_ulltoa_n(value, a);
 Ranier> }

No. While it doesn't matter so much for pg_lltoa since that's unlikely
to inline multiple pg_ulltoa_n calls, if you do pg_ltoa like this it (a)
ends up with two copies of pg_ultoa_n inlined into it, and (b) you don't
actually save any useful amount of time. Your version is also failing to
add the terminating '\0' for the positive case and has other obvious
bugs.
(a) Sorry, I'm not asm specialist.

#include <stdio.h>

int pg_utoa(unsigned int num, char * a) {
    int len;

    len = sprintf(a, "%lu", num);

    return len;
}

int pg_toa(int num, char * a)
{
    if (num < 0) {
       int len;
       len = pg_utoa(num, a);
       a[len] = '\0';
       return len;
    }
    else
       return pg_utoa(num, a);
}
 

.LC0:
        .string "%lu"
pg_utoa(unsigned int, char*):
        mov     edxedi
        xor     eaxeax
        mov     rdirsi
        mov     esiOFFSET FLAT:.LC0
        jmp     sprintf
pg_toa(int, char*):
        push    rbp
        test    ediedi
        mov     rbprsi
        mov     edxedi
        mov     esiOFFSET FLAT:.LC0
        mov     rdirbp
        mov     eax0
        js      .L7
        pop     rbp
        jmp     sprintf
.L7:
        call    sprintf
        movsx   rdxeax
        mov     BYTE PTR [rbp+0+rdx]0
        pop     rbp
        ret

Where " ends up with two copies of pg_ultoa_n inlined into it", in this simplified example?

(b) I call this tail cut, I believe it saves time, for sure.

Regarding bugs:

(c) your version don't check size of a var, when pg_ulltoa_n
warning about "least MAXINT8LEN bytes."

So in theory, I could blow it up, by calling pg_lltoa.

(d) So I can't trust pg_ulltoa_n, when var a, is it big enough?
If not, there are more bugs.

regards,
Ranier Vilela

pgsql-hackers by date:

Previous
From: Jeff Davis
Date:
Subject: Re: Disallow cancellation of waiting for synchronous replication
Next
From: Andrew Gierth
Date:
Subject: Re: Speedup usages of pg_*toa() functions