Skip to content

Commit 2a2e40a

Browse files
committed
pg_upgrade: dramatically reduce memory consumption
Report from Jeff Janes
1 parent f9bb944 commit 2a2e40a

File tree

3 files changed

+66
-34
lines changed

3 files changed

+66
-34
lines changed

contrib/pg_upgrade/check.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -707,28 +707,28 @@ create_script_for_old_cluster_deletion(char **deletion_script_file_name)
707707
fprintf(script, "\n");
708708
/* remove PG_VERSION? */
709709
if (GET_MAJOR_VERSION(old_cluster.major_version) <= 804)
710-
fprintf(script, RM_CMD " %s%s%cPG_VERSION\n",
710+
fprintf(script, RM_CMD " %s%cPG_VERSION\n",
711711
fix_path_separator(os_info.old_tablespaces[tblnum]),
712-
fix_path_separator(old_cluster.tablespace_suffix),
713712
PATH_SEPARATOR);
714713

715714
for (dbnum = 0; dbnum < old_cluster.dbarr.ndbs; dbnum++)
716-
{
717-
fprintf(script, RMDIR_CMD " %s%s%c%d\n",
715+
fprintf(script, RMDIR_CMD " %s%c%d\n",
718716
fix_path_separator(os_info.old_tablespaces[tblnum]),
719-
fix_path_separator(old_cluster.tablespace_suffix),
720717
PATH_SEPARATOR, old_cluster.dbarr.dbs[dbnum].db_oid);
721-
}
722718
}
723719
else
720+
{
721+
char *suffix_path = pg_strdup(old_cluster.tablespace_suffix);
724722

725723
/*
726724
* Simply delete the tablespace directory, which might be ".old"
727725
* or a version-specific subdirectory.
728726
*/
729727
fprintf(script, RMDIR_CMD " %s%s\n",
730728
fix_path_separator(os_info.old_tablespaces[tblnum]),
731-
fix_path_separator(old_cluster.tablespace_suffix));
729+
fix_path_separator(suffix_path));
730+
pfree(suffix_path);
731+
}
732732
}
733733

734734
fclose(script);

contrib/pg_upgrade/info.c

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -108,20 +108,18 @@ create_rel_filename_map(const char *old_data, const char *new_data,
108108
* relation belongs to the default tablespace, hence relfiles should
109109
* exist in the data directories.
110110
*/
111-
strlcpy(map->old_tablespace, old_data, sizeof(map->old_tablespace));
112-
strlcpy(map->new_tablespace, new_data, sizeof(map->new_tablespace));
113-
strlcpy(map->old_tablespace_suffix, "/base", sizeof(map->old_tablespace_suffix));
114-
strlcpy(map->new_tablespace_suffix, "/base", sizeof(map->new_tablespace_suffix));
111+
map->old_tablespace = old_data;
112+
map->new_tablespace = new_data;
113+
map->old_tablespace_suffix = "/base";
114+
map->new_tablespace_suffix = "/base";
115115
}
116116
else
117117
{
118118
/* relation belongs to a tablespace, so use the tablespace location */
119-
strlcpy(map->old_tablespace, old_rel->tablespace, sizeof(map->old_tablespace));
120-
strlcpy(map->new_tablespace, new_rel->tablespace, sizeof(map->new_tablespace));
121-
strlcpy(map->old_tablespace_suffix, old_cluster.tablespace_suffix,
122-
sizeof(map->old_tablespace_suffix));
123-
strlcpy(map->new_tablespace_suffix, new_cluster.tablespace_suffix,
124-
sizeof(map->new_tablespace_suffix));
119+
map->old_tablespace = old_rel->tablespace;
120+
map->new_tablespace = new_rel->tablespace;
121+
map->old_tablespace_suffix = old_cluster.tablespace_suffix;
122+
map->new_tablespace_suffix = new_cluster.tablespace_suffix;
125123
}
126124

127125
map->old_db_oid = old_db->db_oid;
@@ -231,7 +229,7 @@ get_db_infos(ClusterInfo *cluster)
231229
{
232230
dbinfos[tupnum].db_oid = atooid(PQgetvalue(res, tupnum, i_oid));
233231
dbinfos[tupnum].db_name = pg_strdup(PQgetvalue(res, tupnum, i_datname));
234-
snprintf(dbinfos[tupnum].db_tblspace, sizeof(dbinfos[tupnum].db_tblspace), "%s",
232+
snprintf(dbinfos[tupnum].db_tablespace, sizeof(dbinfos[tupnum].db_tablespace), "%s",
235233
PQgetvalue(res, tupnum, i_spclocation));
236234
}
237235
PQclear(res);
@@ -264,13 +262,15 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
264262
int num_rels = 0;
265263
char *nspname = NULL;
266264
char *relname = NULL;
265+
char *tablespace = NULL;
267266
int i_spclocation,
268267
i_nspname,
269268
i_relname,
270269
i_oid,
271270
i_relfilenode,
272271
i_reltablespace;
273272
char query[QUERY_ALLOC];
273+
char *last_namespace = NULL, *last_tablespace = NULL;
274274

275275
/*
276276
* pg_largeobject contains user data that does not appear in pg_dumpall
@@ -366,26 +366,53 @@ get_rel_infos(ClusterInfo *cluster, DbInfo *dbinfo)
366366
for (relnum = 0; relnum < ntups; relnum++)
367367
{
368368
RelInfo *curr = &relinfos[num_rels++];
369-
const char *tblspace;
370369

371370
curr->reloid = atooid(PQgetvalue(res, relnum, i_oid));
372371

373372
nspname = PQgetvalue(res, relnum, i_nspname);
374-
curr->nspname = pg_strdup(nspname);
373+
curr->nsp_alloc = false;
374+
375+
/*
376+
* Many of the namespace and tablespace strings are identical,
377+
* so we try to reuse the allocated string pointers where possible
378+
* to reduce memory consumption.
379+
*/
380+
/* Can we reuse the previous string allocation? */
381+
if (last_namespace && strcmp(nspname, last_namespace) == 0)
382+
curr->nspname = last_namespace;
383+
else
384+
{
385+
last_namespace = curr->nspname = pg_strdup(nspname);
386+
curr->nsp_alloc = true;
387+
}
375388

376389
relname = PQgetvalue(res, relnum, i_relname);
377390
curr->relname = pg_strdup(relname);
378391

379392
curr->relfilenode = atooid(PQgetvalue(res, relnum, i_relfilenode));
393+
curr->tblsp_alloc = false;
380394

395+
/* Is the tablespace oid non-zero? */
381396
if (atooid(PQgetvalue(res, relnum, i_reltablespace)) != 0)
382-
/* Might be "", meaning the cluster default location. */
383-
tblspace = PQgetvalue(res, relnum, i_spclocation);
397+
{
398+
/*
399+
* The tablespace location might be "", meaning the cluster
400+
* default location, i.e. pg_default or pg_global.
401+
*/
402+
tablespace = PQgetvalue(res, relnum, i_spclocation);
403+
404+
/* Can we reuse the previous string allocation? */
405+
if (last_tablespace && strcmp(tablespace, last_tablespace) == 0)
406+
curr->tablespace = last_tablespace;
407+
else
408+
{
409+
last_tablespace = curr->tablespace = pg_strdup(tablespace);
410+
curr->tblsp_alloc = true;
411+
}
412+
}
384413
else
385-
/* A zero reltablespace indicates the database tablespace. */
386-
tblspace = dbinfo->db_tblspace;
387-
388-
strlcpy(curr->tablespace, tblspace, sizeof(curr->tablespace));
414+
/* A zero reltablespace oid indicates the database tablespace. */
415+
curr->tablespace = dbinfo->db_tablespace;
389416
}
390417
PQclear(res);
391418

@@ -419,8 +446,11 @@ free_rel_infos(RelInfoArr *rel_arr)
419446

420447
for (relnum = 0; relnum < rel_arr->nrels; relnum++)
421448
{
422-
pg_free(rel_arr->rels[relnum].nspname);
449+
if (rel_arr->rels[relnum].nsp_alloc)
450+
pg_free(rel_arr->rels[relnum].nspname);
423451
pg_free(rel_arr->rels[relnum].relname);
452+
if (rel_arr->rels[relnum].tblsp_alloc)
453+
pg_free(rel_arr->rels[relnum].tablespace);
424454
}
425455
pg_free(rel_arr->rels);
426456
rel_arr->nrels = 0;

contrib/pg_upgrade/pg_upgrade.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ typedef struct
127127
Oid reloid; /* relation oid */
128128
Oid relfilenode; /* relation relfile node */
129129
/* relation tablespace path, or "" for the cluster default */
130-
char tablespace[MAXPGPATH];
130+
char *tablespace;
131+
bool nsp_alloc;
132+
bool tblsp_alloc;
131133
} RelInfo;
132134

133135
typedef struct
@@ -141,10 +143,10 @@ typedef struct
141143
*/
142144
typedef struct
143145
{
144-
char old_tablespace[MAXPGPATH];
145-
char new_tablespace[MAXPGPATH];
146-
char old_tablespace_suffix[MAXPGPATH];
147-
char new_tablespace_suffix[MAXPGPATH];
146+
const char *old_tablespace;
147+
const char *new_tablespace;
148+
const char *old_tablespace_suffix;
149+
const char *new_tablespace_suffix;
148150
Oid old_db_oid;
149151
Oid new_db_oid;
150152

@@ -166,7 +168,7 @@ typedef struct
166168
{
167169
Oid db_oid; /* oid of the database */
168170
char *db_name; /* database name */
169-
char db_tblspace[MAXPGPATH]; /* database default tablespace path */
171+
char db_tablespace[MAXPGPATH]; /* database default tablespace path */
170172
RelInfoArr rel_arr; /* array of all user relinfos */
171173
} DbInfo;
172174

@@ -256,7 +258,7 @@ typedef struct
256258
Oid pg_database_oid; /* OID of pg_database relation */
257259
Oid install_role_oid; /* OID of connected role */
258260
Oid role_count; /* number of roles defined in the cluster */
259-
char *tablespace_suffix; /* directory specification */
261+
const char *tablespace_suffix; /* directory specification */
260262
} ClusterInfo;
261263

262264

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