Re: [HACKERS] Postgres Speed or lack thereof

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Magnus Hagander <mha(at)sollentuna(dot)net>
Cc: pgsql-hackers(at)postgreSQL(dot)org
Subject: Re: [HACKERS] Postgres Speed or lack thereof
Date: 1999-01-18 16:37:12
Message-ID: 423.916677432@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Magnus Hagander <mha(at)sollentuna(dot)net> writes:
> I don't know, maybe recv() is more expensive than fgetc()?

Vastly.

recv() is a kernel call. You have the overhead of getting control into
the kernel, normally several times more expensive than a function call;
of passing parameters back and forth from user space to kernel space
(for example, the kernel will probably have to translate and range-check
the buffer pointer you pass it, to ensure you can't fool the kernel into
scribbling on some other process's memory); of verifying that the
descriptor number you pass is open and you have permission to read it;
and of finding the associated data buffer. Plus the scheduler may
run to reconsider whether to give control back to you, or switch off to
another user process. Etc etc etc.

fgetc() is a plain C function that normally just has to fetch the next
byte out of a buffer that's already been read into your address space
--- that is, when you're using stdio, you pay all the above-described
kernel interaction overhead once per bufferload, not once per character.

If you use getc(), which is allowed to be a macro, you don't even pay
the function-call overhead; that form is probably less than a dozen
instructions, except when the buffer is empty. Judging by the profile
numbers, recv()'ing a single character takes close to 1400 instructions
on my system.

> An interesting fact is that pq_getchar() doesn't show up at all. Could be
> because it's fast, but still executed many times, right?

Right, it doesn't run long enough to get itself into the top functions.
It's there though --- the dynamic profile shows:

-----------------------------------------------
0.03 18.83 5001/5001 ReadCommand [27]
[28] 10.4 0.03 18.83 5001 SocketBackend [28]
0.00 18.73 5000/5000 pq_getstr [30]
0.01 0.09 5001/5001 pq_getnchar [303]
-----------------------------------------------
0.00 18.73 5000/5000 SocketBackend [28]
[30] 10.4 0.00 18.73 5000 pq_getstr [30]
0.11 18.62 5000/5000 pqGetString [29]
-----------------------------------------------
0.11 18.62 5000/5000 pq_getstr [30]
[29] 10.4 0.11 18.62 5000 pqGetString [29]
0.47 18.15 957186/957186 pq_getchar [31]
-----------------------------------------------
0.47 18.15 957186/957186 pqGetString [29]
[31] 10.3 0.47 18.15 957186 pq_getchar [31]
18.15 0.00 957186/962187 recv [32]
-----------------------------------------------
0.09 0.00 5001/962187 pqGetNBytes [315]
18.15 0.00 957186/962187 pq_getchar [31]
[32] 10.1 18.24 0.00 962187 recv [32]
-----------------------------------------------

In the old code with fgetc(), the execution time of fgetc() was probably
not much worse than pq_getchar --- ie, about half a second not 18
seconds for this test sequence...

What we need to do here is to re-introduce the buffering ability of
stdio into backend libpq. If you compare the current frontend libpq,
you'll notice that it reads or writes the socket a bufferload at a time,
not a character at a time.

regards, tom lane

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 1999-01-18 16:47:32 Re: [HACKERS] Postgres Speed or lack thereof
Previous Message Bruce Momjian 1999-01-18 16:36:48 Re: [HACKERS] Syntax errors in current tree