From de5cd5744012a1ec1b20b16863ce24f45f30aac6 Mon Sep 17 00:00:00 2001 From: Filip Janus Date: Wed, 12 Nov 2025 14:29:43 +0100 Subject: [PATCH 1/2] Add configurable receive buffer size This commit introduces a new GUC parameter 'pq_recv_buffer_size' to allow users to configure the size of the network receive buffer for each backend connection. The receive buffer is now dynamically allocated instead of using a fixed compile-time size. Key changes: - Make PqRecvBuffer dynamically allocated based on pq_recv_buffer_size GUC - Add pq_recv_buffer_size GUC parameter (default 8KB, min 8KB, max configurable) has enough space Benefits: - Configurable buffer size allows tuning for workloads with large messages - Maintains backward compatibility with 8KB default --- src/backend/libpq/pqcomm.c | 14 +++++++++----- src/backend/utils/init/globals.c | 3 +++ src/backend/utils/misc/guc_parameters.dat | 10 ++++++++++ src/backend/utils/misc/postgresql.conf.sample | 1 + src/include/miscadmin.h | 1 + 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 25f739a6a17..d4bd412b68d 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -112,19 +112,21 @@ static List *sock_paths = NIL; /* * Buffers for low-level I/O. * - * The receive buffer is fixed size. Send buffer is usually 8k, but can be - * enlarged by pq_putmessage_noblock() if the message doesn't fit otherwise. + * Both send and receive buffers are dynamically allocated. Send buffer is + * usually 8k, but can be enlarged by pq_putmessage_noblock() if the message + * doesn't fit otherwise. Receive buffer size is configurable via the + * pq_recv_buffer_size GUC parameter. */ #define PQ_SEND_BUFFER_SIZE 8192 -#define PQ_RECV_BUFFER_SIZE 8192 static char *PqSendBuffer; static int PqSendBufferSize; /* Size send buffer */ static size_t PqSendPointer; /* Next index to store a byte in PqSendBuffer */ static size_t PqSendStart; /* Next index to send a byte in PqSendBuffer */ -static char PqRecvBuffer[PQ_RECV_BUFFER_SIZE]; +static char *PqRecvBuffer; /* Dynamically allocated receive buffer */ +static int PqRecvBufferSize; /* Size of receive buffer */ static int PqRecvPointer; /* Next index to read a byte from PqRecvBuffer */ static int PqRecvLength; /* End of data available in PqRecvBuffer */ @@ -278,6 +280,8 @@ pq_init(ClientSocket *client_sock) /* initialize state variables */ PqSendBufferSize = PQ_SEND_BUFFER_SIZE; PqSendBuffer = MemoryContextAlloc(TopMemoryContext, PqSendBufferSize); + PqRecvBufferSize = pq_recv_buffer_size * 1024; /* GUC is in KB */ + PqRecvBuffer = MemoryContextAlloc(TopMemoryContext, PqRecvBufferSize); PqSendPointer = PqSendStart = PqRecvPointer = PqRecvLength = 0; PqCommBusy = false; PqCommReadingMsg = false; @@ -921,7 +925,7 @@ pq_recvbuf(void) errno = 0; r = secure_read(MyProcPort, PqRecvBuffer + PqRecvLength, - PQ_RECV_BUFFER_SIZE - PqRecvLength); + PqRecvBufferSize - PqRecvLength); if (r < 0) { diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index d31cb45a058..5fdf1293d2e 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -165,3 +165,6 @@ int notify_buffers = 16; int serializable_buffers = 32; int subtransaction_buffers = 0; int transaction_buffers = 0; + +/* network buffer sizes */ +int pq_recv_buffer_size = 8; diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat index 1128167c025..51816d31807 100644 --- a/src/backend/utils/misc/guc_parameters.dat +++ b/src/backend/utils/misc/guc_parameters.dat @@ -2259,6 +2259,16 @@ max => 'INT_MAX / 1000000', }, +{ name => 'pq_recv_buffer_size', type => 'int', context => 'PGC_BACKEND', group => 'RESOURCES_MEM', + short_desc => 'Sets the size of the network receive buffer for each backend.', + long_desc => 'Larger values can improve performance when receiving large messages, but consume more memory per connection.', + flags => 'GUC_UNIT_KB', + variable => 'pq_recv_buffer_size', + boot_val => '8', + min => '8', + max => 'MAX_KILOBYTES', +}, + # Not for general use { name => 'pre_auth_delay', type => 'int', context => 'PGC_SIGHUP', group => 'DEVELOPER_OPTIONS', short_desc => 'Sets the amount of time to wait before authentication on connection startup.', diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index dc9e2255f8a..4bb56b4cbb0 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -136,6 +136,7 @@ #huge_page_size = 0 # zero for system default # (change requires restart) #temp_buffers = 8MB # min 800kB +#pq_recv_buffer_size = 8kB # min 8kB #max_prepared_transactions = 0 # zero disables the feature # (change requires restart) # Caution: it is not advisable to set max_prepared_transactions nonzero unless diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index 9a7d733ddef..2e51235ee6a 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -186,6 +186,7 @@ extern PGDLLIMPORT int notify_buffers; extern PGDLLIMPORT int serializable_buffers; extern PGDLLIMPORT int subtransaction_buffers; extern PGDLLIMPORT int transaction_buffers; +extern PGDLLIMPORT int pq_recv_buffer_size; extern PGDLLIMPORT int MyProcPid; extern PGDLLIMPORT pg_time_t MyStartTime; -- 2.39.5 (Apple Git-154)