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

+7-7
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

+50-20
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

+9-7
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)