From dac67d43f93bfcfd24f2871b0b1089fcd34b9c3e Mon Sep 17 00:00:00 2001 From: Lew Rossman Date: Fri, 24 Nov 2023 14:03:29 -0500 Subject: [PATCH] Reduce reallocs in EN_addnode & EN_addlink --- src/epanet.c | 42 ++++++++++++++++++++++++++---------------- src/project.c | 17 ++++++++++++----- src/types.h | 5 ++++- src/validate.c | 5 +---- 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/epanet.c b/src/epanet.c index 86b510ba..5d3fef85 100644 --- a/src/epanet.c +++ b/src/epanet.c @@ -27,6 +27,8 @@ #define snprintf _snprintf #endif +const int DELTA_CAPACITY = 50; + /******************************************************************** Project Functions @@ -1858,15 +1860,19 @@ int DLLEXPORT EN_addnode(EN_Project p, const char *id, int nodeType, int *index) if (nodeType < EN_JUNCTION || nodeType > EN_TANK) return 251; // Grow node-related arrays to accomodate the new node - size = (net->Nnodes + 2) * sizeof(Snode); - net->Node = (Snode *)realloc(net->Node, size); - size = (net->Nnodes + 2) * sizeof(double); - hyd->NodeDemand = (double *)realloc(hyd->NodeDemand, size); - qual->NodeQual = (double *)realloc(qual->NodeQual, size); - hyd->NodeHead = (double *)realloc(hyd->NodeHead, size); - hyd->DemandFlow = (double *)realloc(hyd->DemandFlow, size); - hyd->EmitterFlow = (double *)realloc(hyd->EmitterFlow, size); - + if (net->Nnodes == net->NodeCapacity) + { + net->NodeCapacity += DELTA_CAPACITY; + size = (net->NodeCapacity + 1) * sizeof(Snode); + net->Node = (Snode *)realloc(net->Node, size); + size = (net->NodeCapacity + 1) * sizeof(double); + hyd->NodeDemand = (double *)realloc(hyd->NodeDemand, size); + qual->NodeQual = (double *)realloc(qual->NodeQual, size); + hyd->NodeHead = (double *)realloc(hyd->NodeHead, size); + hyd->DemandFlow = (double *)realloc(hyd->DemandFlow, size); + hyd->EmitterFlow = (double *)realloc(hyd->EmitterFlow, size); + } + // Actions taken when a new Junction is added if (nodeType == EN_JUNCTION) { @@ -3247,16 +3253,20 @@ int DLLEXPORT EN_addlink(EN_Project p, const char *id, int linkType, } // Grow link-related arrays to accomodate the new link + if (net->Nlinks == net->LinkCapacity) + { + net->LinkCapacity += DELTA_CAPACITY; + size = (net->LinkCapacity + 1) * sizeof(Slink); + net->Link = (Slink *)realloc(net->Link, size); + size = (net->LinkCapacity + 1) * sizeof(double); + hyd->LinkFlow = (double *)realloc(hyd->LinkFlow, size); + hyd->LinkSetting = (double *)realloc(hyd->LinkSetting, size); + size = (net->LinkCapacity + 1) * sizeof(StatusType); + hyd->LinkStatus = (StatusType *)realloc(hyd->LinkStatus, size); + } net->Nlinks++; p->parser.MaxLinks = net->Nlinks; n = net->Nlinks; - size = (n + 1) * sizeof(Slink); - net->Link = (Slink *)realloc(net->Link, size); - size = (n + 1) * sizeof(double); - hyd->LinkFlow = (double *)realloc(hyd->LinkFlow, size); - hyd->LinkSetting = (double *)realloc(hyd->LinkSetting, size); - size = (n + 1) * sizeof(StatusType); - hyd->LinkStatus = (StatusType *)realloc(hyd->LinkStatus, size); // Set properties for the new link link = &net->Link[n]; diff --git a/src/project.c b/src/project.c index 2104d060..138fdf4e 100644 --- a/src/project.c +++ b/src/project.c @@ -318,6 +318,9 @@ void initpointers(Project *pr) nw->Nrules = 0; nw->Npats = 0; nw->Ncurves = 0; + + nw->NodeCapacity = 0; + nw->LinkCapacity = 0; pr->hydraul.NodeDemand = NULL; pr->hydraul.NodeHead = NULL; @@ -387,6 +390,7 @@ int allocdata(Project *pr) //************************************************************* if (!errcode) { + pr->network.NodeCapacity = pr->parser.MaxNodes; n = pr->parser.MaxNodes + 1; pr->network.Node = (Snode *)calloc(n, sizeof(Snode)); pr->hydraul.NodeDemand = (double *)calloc(n, sizeof(double)); @@ -405,6 +409,7 @@ int allocdata(Project *pr) // Allocate memory for network links if (!errcode) { + pr->network.LinkCapacity = pr->parser.MaxLinks; n = pr->parser.MaxLinks + 1; pr->network.Link = (Slink *)calloc(n, sizeof(Slink)); pr->hydraul.LinkFlow = (double *)calloc(n, sizeof(double)); @@ -489,6 +494,7 @@ void freedata(Project *pr) free(pr->network.Node[j].Comment); } free(pr->network.Node); + pr->network.NodeCapacity = 0; } // Free memory for link data @@ -499,14 +505,15 @@ void freedata(Project *pr) freelinkvertices(&pr->network.Link[j]); free(pr->network.Link[j].Comment); } + free(pr->network.Link); + pr->network.LinkCapacity = 0; } - free(pr->network.Link); // Free memory for other network objects - free(pr->network.Tank); - free(pr->network.Pump); - free(pr->network.Valve); - free(pr->network.Control); + if (pr->network.Tank != NULL) free(pr->network.Tank); + if (pr->network.Pump != NULL) free(pr->network.Pump); + if (pr->network.Valve != NULL) free(pr->network.Valve); + if (pr->network.Control != NULL) free(pr->network.Control); // Free memory for time patterns if (pr->network.Pattern != NULL) diff --git a/src/types.h b/src/types.h index ff7c3599..359eddaf 100755 --- a/src/types.h +++ b/src/types.h @@ -838,7 +838,10 @@ typedef struct { Ncontrols, // Number of simple controls Nrules, // Number of control rules Npats, // Number of time patterns - Ncurves; // Number of data curves + Ncurves, // Number of data curves + + NodeCapacity, + LinkCapacity; Snode *Node; // Node array Slink *Link; // Link array diff --git a/src/validate.c b/src/validate.c index 978d8f47..3633116f 100644 --- a/src/validate.c +++ b/src/validate.c @@ -359,7 +359,7 @@ void reindextanks(Project *pr) Parser *parser = &pr->parser; Quality *qual = &pr->quality; Scontrol *control; - int i, j, ndiff, n1, n2, size; + int i, j, ndiff, n1, n2; // ndiff = # unused entries in Node array before first tank node ndiff = parser->MaxJuncs - net->Njuncs; @@ -395,11 +395,8 @@ void reindextanks(Project *pr) if (qual->TraceNode == n1) qual->TraceNode = n2; } - // Reallocate the Node array (shouldn't fail as new size < old size) parser->MaxJuncs = net->Njuncs; parser->MaxNodes = net->Njuncs + net->Ntanks; - size = (net->Nnodes + 2) * sizeof(Snode); - net->Node = (Snode *)realloc(net->Node, size); } }