Re: Speedup usages of pg_*toa() functions

From: Ranier Vilela <ranier(dot)vf(at)gmail(dot)com>
To: Andrew Gierth <andrew(at)tao11(dot)riddles(dot)org(dot)uk>
Cc: David Rowley <dgrowleyml(at)gmail(dot)com>, PostgreSQL Developers <pgsql-hackers(at)lists(dot)postgresql(dot)org>, Andres Freund <andres(at)anarazel(dot)de>
Subject: Re: Speedup usages of pg_*toa() functions
Date: 2020-06-09 18:37:57
Message-ID: CAEudQAoKAZ1GNNb_wkKmYTqvbkbYEHP97OhOW-Hi_1kMpmg3+g@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Em ter., 9 de jun. de 2020 às 13:01, Andrew Gierth <
andrew(at)tao11(dot)riddles(dot)org(dot)uk> escreveu:

> >>>>> "Ranier" == Ranier Vilela <ranier(dot)vf(at)gmail(dot)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 edx, edi
xor eax, eax
mov rdi, rsi
mov esi, OFFSET FLAT:.LC0
jmp sprintf
pg_toa(int, char*):
push rbp
test edi, edi
mov rbp, rsi
mov edx, edi
mov esi, OFFSET FLAT:.LC0
mov rdi, rbp
mov eax, 0
js .L7
pop rbp
jmp sprintf
.L7:
call sprintf
movsx rdx, eax
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

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andrew Gierth 2020-06-09 18:52:59 Re: Speedup usages of pg_*toa() functions
Previous Message Jeff Davis 2020-06-09 18:32:51 Re: Disallow cancellation of waiting for synchronous replication