Skip to content

Commit 10f6646

Browse files
committed
Introduce io_max_combine_limit.
The existing io_combine_limit can be changed by users. The new io_max_combine_limit is fixed at server startup time, and functions as a silent clamp on the user setting. That in itself is probably quite useful, but the primary motivation is: aio_init.c allocates shared memory for all asynchronous IOs including some per-block data, and we didn't want to waste memory you'd never used by assuming they could be up to PG_IOV_MAX. This commit already halves the size of 'AioHandleIov' and 'AioHandleData'. A follow-up commit can now expand PG_IOV_MAX without affecting that. Since our GUC system doesn't support dependencies or cross-checks between GUCs, the user-settable one now assigns a "raw" value to io_combine_limit_guc, and the lower of io_combine_limit_guc and io_max_combine_limit is maintained in io_combine_limit. Reviewed-by: Andres Freund <andres@anarazel.de> (earlier version) Discussion: https://postgr.es/m/CA%2BhUKG%2B2T9p-%2BzM6Eeou-RAJjTML6eit1qn26f9twznX59qtCA%40mail.gmail.com
1 parent 17d8bba commit 10f6646

File tree

8 files changed

+72
-15
lines changed

8 files changed

+72
-15
lines changed

doc/src/sgml/config.sgml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2625,6 +2625,24 @@ include_dir 'conf.d'
26252625
</listitem>
26262626
</varlistentry>
26272627

2628+
<varlistentry id="guc-io-max-combine-limit" xreflabel="io_max_combine_limit">
2629+
<term><varname>io_max_combine_limit</varname> (<type>integer</type>)
2630+
<indexterm>
2631+
<primary><varname>io_max_combine_limit</varname> configuration parameter</primary>
2632+
</indexterm>
2633+
</term>
2634+
<listitem>
2635+
<para>
2636+
Controls the largest I/O size in operations that combine I/O, and silently
2637+
limits the user-settable parameter <varname>io_combine_limit</varname>.
2638+
This parameter can only be set in
2639+
the <filename>postgresql.conf</filename> file or on the server
2640+
command line.
2641+
The default is 128kB.
2642+
</para>
2643+
</listitem>
2644+
</varlistentry>
2645+
26282646
<varlistentry id="guc-io-combine-limit" xreflabel="io_combine_limit">
26292647
<term><varname>io_combine_limit</varname> (<type>integer</type>)
26302648
<indexterm>
@@ -2633,7 +2651,10 @@ include_dir 'conf.d'
26332651
</term>
26342652
<listitem>
26352653
<para>
2636-
Controls the largest I/O size in operations that combine I/O.
2654+
Controls the largest I/O size in operations that combine I/O. If set
2655+
higher than the <varname>io_max_combine_limit</varname> parameter, the
2656+
lower value will silently be used instead, so both may need to be raised
2657+
to increase the I/O size.
26372658
The default is 128kB.
26382659
</para>
26392660
</listitem>

src/backend/commands/variable.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,24 @@ assign_maintenance_io_concurrency(int newval, void *extra)
11561156
#endif
11571157
}
11581158

1159+
/*
1160+
* GUC assign hooks that recompute io_combine_limit whenever
1161+
* io_combine_limit_guc and io_max_combine_limit are changed. These are needed
1162+
* because the GUC subsystem doesn't support dependencies between GUCs, and
1163+
* they may be assigned in either order.
1164+
*/
1165+
void
1166+
assign_io_max_combine_limit(int newval, void *extra)
1167+
{
1168+
io_max_combine_limit = newval;
1169+
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
1170+
}
1171+
void
1172+
assign_io_combine_limit(int newval, void *extra)
1173+
{
1174+
io_combine_limit_guc = newval;
1175+
io_combine_limit = Min(io_max_combine_limit, io_combine_limit_guc);
1176+
}
11591177

11601178
/*
11611179
* These show hooks just exist because we want to show the values in octal.

src/backend/storage/aio/aio_init.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "storage/aio.h"
1919
#include "storage/aio_internal.h"
2020
#include "storage/aio_subsys.h"
21+
#include "storage/bufmgr.h"
2122
#include "storage/io_worker.h"
2223
#include "storage/ipc.h"
2324
#include "storage/proc.h"
@@ -72,15 +73,9 @@ AioHandleShmemSize(void)
7273
static Size
7374
AioHandleIOVShmemSize(void)
7475
{
75-
/*
76-
* Each IO handle can have an PG_IOV_MAX long iovec.
77-
*
78-
* XXX: Right now the amount of space available for each IO is PG_IOV_MAX.
79-
* While it's tempting to use the io_combine_limit GUC, that's
80-
* PGC_USERSET, so we can't allocate shared memory based on that.
81-
*/
76+
/* each IO handle can have up to io_max_combine_limit iovec objects */
8277
return mul_size(sizeof(struct iovec),
83-
mul_size(mul_size(PG_IOV_MAX, AioProcs()),
78+
mul_size(mul_size(io_max_combine_limit, AioProcs()),
8479
io_max_concurrency));
8580
}
8681

@@ -89,7 +84,7 @@ AioHandleDataShmemSize(void)
8984
{
9085
/* each buffer referenced by an iovec can have associated data */
9186
return mul_size(sizeof(uint64),
92-
mul_size(mul_size(PG_IOV_MAX, AioProcs()),
87+
mul_size(mul_size(io_max_combine_limit, AioProcs()),
9388
io_max_concurrency));
9489
}
9590

@@ -160,7 +155,7 @@ AioShmemInit(void)
160155
bool found;
161156
uint32 io_handle_off = 0;
162157
uint32 iovec_off = 0;
163-
uint32 per_backend_iovecs = io_max_concurrency * PG_IOV_MAX;
158+
uint32 per_backend_iovecs = io_max_concurrency * io_max_combine_limit;
164159

165160
pgaio_ctl = (PgAioCtl *)
166161
ShmemInitStruct("AioCtl", AioCtlShmemSize(), &found);
@@ -213,7 +208,7 @@ AioShmemInit(void)
213208
ConditionVariableInit(&ioh->cv);
214209

215210
dclist_push_tail(&bs->idle_ios, &ioh->node);
216-
iovec_off += PG_IOV_MAX;
211+
iovec_off += io_max_combine_limit;
217212
}
218213
}
219214

src/backend/storage/buffer/bufmgr.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,12 @@ int maintenance_io_concurrency = DEFAULT_MAINTENANCE_IO_CONCURRENCY;
160160
/*
161161
* Limit on how many blocks should be handled in single I/O operations.
162162
* StartReadBuffers() callers should respect it, as should other operations
163-
* that call smgr APIs directly.
163+
* that call smgr APIs directly. It is computed as the minimum of underlying
164+
* GUCs io_combine_limit_guc and io_max_combine_limit.
164165
*/
165166
int io_combine_limit = DEFAULT_IO_COMBINE_LIMIT;
167+
int io_combine_limit_guc = DEFAULT_IO_COMBINE_LIMIT;
168+
int io_max_combine_limit = DEFAULT_IO_COMBINE_LIMIT;
166169

167170
/*
168171
* GUC variables about triggering kernel writeback for buffers written; OS

src/backend/utils/misc/guc_tables.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3252,6 +3252,20 @@ struct config_int ConfigureNamesInt[] =
32523252
NULL
32533253
},
32543254

3255+
{
3256+
{"io_max_combine_limit",
3257+
PGC_POSTMASTER,
3258+
RESOURCES_IO,
3259+
gettext_noop("Server-wide limit that clamps io_combine_limit."),
3260+
NULL,
3261+
GUC_UNIT_BLOCKS
3262+
},
3263+
&io_max_combine_limit,
3264+
DEFAULT_IO_COMBINE_LIMIT,
3265+
1, MAX_IO_COMBINE_LIMIT,
3266+
NULL, assign_io_max_combine_limit, NULL
3267+
},
3268+
32553269
{
32563270
{"io_combine_limit",
32573271
PGC_USERSET,
@@ -3263,7 +3277,7 @@ struct config_int ConfigureNamesInt[] =
32633277
&io_combine_limit,
32643278
DEFAULT_IO_COMBINE_LIMIT,
32653279
1, MAX_IO_COMBINE_LIMIT,
3266-
NULL, NULL, NULL
3280+
NULL, assign_io_combine_limit, NULL
32673281
},
32683282

32693283
{

src/backend/utils/misc/postgresql.conf.sample

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@
200200
#backend_flush_after = 0 # measured in pages, 0 disables
201201
#effective_io_concurrency = 16 # 1-1000; 0 disables prefetching
202202
#maintenance_io_concurrency = 16 # 1-1000; 0 disables prefetching
203+
#io_max_combine_limit = 128kB # usually 1-32 blocks (depends on OS)
204+
# (change requires restart)
203205
#io_combine_limit = 128kB # usually 1-32 blocks (depends on OS)
204206

205207
#io_method = worker # worker, sync (change requires restart)

src/include/storage/bufmgr.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,9 @@ extern PGDLLIMPORT int maintenance_io_concurrency;
163163

164164
#define MAX_IO_COMBINE_LIMIT PG_IOV_MAX
165165
#define DEFAULT_IO_COMBINE_LIMIT Min(MAX_IO_COMBINE_LIMIT, (128 * 1024) / BLCKSZ)
166-
extern PGDLLIMPORT int io_combine_limit;
166+
extern PGDLLIMPORT int io_combine_limit; /* min of the two GUCs below */
167+
extern PGDLLIMPORT int io_combine_limit_guc;
168+
extern PGDLLIMPORT int io_max_combine_limit;
167169

168170
extern PGDLLIMPORT int checkpoint_flush_after;
169171
extern PGDLLIMPORT int backend_flush_after;

src/include/utils/guc_hooks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ extern const char *show_log_timezone(void);
8686
extern bool check_maintenance_io_concurrency(int *newval, void **extra,
8787
GucSource source);
8888
extern void assign_maintenance_io_concurrency(int newval, void *extra);
89+
extern void assign_io_max_combine_limit(int newval, void *extra);
90+
extern void assign_io_combine_limit(int newval, void *extra);
8991
extern bool check_max_slot_wal_keep_size(int *newval, void **extra,
9092
GucSource source);
9193
extern void assign_max_wal_size(int newval, void *extra);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy