Skip to content

Commit 605139e

Browse files
committed
Improvements to the overall speed and memory use of libCellML.
1 parent e417b6b commit 605139e

55 files changed

Lines changed: 1442 additions & 1060 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ set(_PROJECT_VERSION 0.6.3)
2222
set(PROJECT_DEVELOPER_VERSION)
2323
project(${PROJECT_NAME} VERSION ${_PROJECT_VERSION} LANGUAGES CXX)
2424

25+
# Set the C++ standard to be used for all targets.
26+
set(CMAKE_CXX_STANDARD 20)
27+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
28+
set(CMAKE_CXX_EXTENSIONS OFF)
29+
2530
# Set policies that affect the build.
2631
set(NEW_POLICIES CMP0056 CMP0063 CMP0074 CMP0078 CMP0086 CMP0092)
2732
foreach(NEW_POLICY ${NEW_POLICIES})

src/analyser.cpp

Lines changed: 174 additions & 101 deletions
Large diffs are not rendered by default.

src/analyser_p.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
#include "libcellml/generatorprofile.h"
1818
#include "libcellml/issue.h"
1919

20+
#include <unordered_set>
21+
2022
#include "analysermodel_p.h"
2123
#include "internaltypes.h"
2224
#include "logger_p.h"
@@ -96,9 +98,12 @@ struct AnalyserInternalEquation
9698
ComponentPtr mComponent;
9799

98100
AnalyserInternalVariablePtrs mVariables;
101+
std::unordered_set<AnalyserInternalVariable *> mVariablesSet;
99102
AnalyserInternalVariablePtrs mStateVariables;
103+
std::unordered_set<AnalyserInternalVariable *> mStateVariablesSet;
100104
AnalyserInternalVariablePtrs mAllVariables;
101105
AnalyserInternalVariablePtrs mUnknownVariables;
106+
std::unordered_set<AnalyserInternalVariable *> mUnknownVariablesSet;
102107

103108
size_t mNlaSystemIndex = MAX_SIZE_T;
104109
AnalyserInternalEquationWeakPtrs mNlaSiblings;
@@ -160,12 +165,13 @@ class Analyser::AnalyserImpl: public Logger::LoggerImpl
160165
AnalyserExternalVariablePtrs mExternalVariables;
161166

162167
AnalyserInternalVariablePtrs mInternalVariables;
168+
std::unordered_map<Variable *, AnalyserInternalVariablePtr> mInternalVariableCache;
163169
AnalyserInternalEquationPtrs mInternalEquations;
164170

165171
GeneratorProfilePtr mGeneratorProfile = GeneratorProfile::create();
166172

167-
std::map<std::string, UnitsPtr> mStandardUnits;
168-
std::map<AnalyserEquationAstPtr, UnitsPtr> mCiCnUnits;
173+
std::unordered_map<std::string, UnitsPtr> mStandardUnits;
174+
std::unordered_map<AnalyserEquationAstPtr, UnitsPtr> mCiCnUnits;
169175

170176
AnalyserImpl();
171177

@@ -181,8 +187,8 @@ class Analyser::AnalyserImpl: public Logger::LoggerImpl
181187
void analyseComponent(const ComponentPtr &component);
182188
void analyseComponentVariables(const ComponentPtr &component);
183189

184-
void equivalentVariables(const VariablePtr &variable,
185-
VariablePtrs &equivalentVariables) const;
190+
void equivalentVariables(const VariablePtr &variable, VariablePtrs &equivalentVariables,
191+
std::unordered_set<Variable *> &seen) const;
186192
VariablePtrs equivalentVariables(const VariablePtr &variable) const;
187193

188194
void analyseEquationAst(const AnalyserEquationAstPtr &ast);
@@ -251,7 +257,7 @@ class Analyser::AnalyserImpl: public Logger::LoggerImpl
251257
static bool isExternalVariable(const AnalyserInternalVariablePtr &variable);
252258

253259
bool isStateRateBased(const AnalyserEquationPtr &analyserEquation,
254-
AnalyserEquationPtrs &checkedEquations);
260+
std::unordered_set<AnalyserEquation *> &checkedEquations);
255261

256262
void addInvalidVariableIssue(const AnalyserInternalVariablePtr &variable,
257263
Issue::ReferenceRule referenceRule);

src/analyserequation.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ std::vector<AnalyserEquationPtr> AnalyserEquation::dependencies() const
9393
{
9494
std::vector<AnalyserEquationPtr> res;
9595

96+
res.reserve(mPimpl->mDependencies.size());
97+
9698
for (const auto &dependency : mPimpl->mDependencies) {
9799
res.push_back(dependency.lock());
98100
}
@@ -123,6 +125,8 @@ std::vector<AnalyserEquationPtr> AnalyserEquation::nlaSiblings() const
123125
{
124126
std::vector<AnalyserEquationPtr> res;
125127

128+
res.reserve(mPimpl->mNlaSiblings.size());
129+
126130
for (const auto &nlaSibling : mPimpl->mNlaSiblings) {
127131
res.push_back(nlaSibling.lock());
128132
}
@@ -149,7 +153,7 @@ size_t AnalyserEquation::stateCount() const
149153
return mPimpl->mStates.size();
150154
}
151155

152-
std::vector<AnalyserVariablePtr> AnalyserEquation::states() const
156+
const std::vector<AnalyserVariablePtr> &AnalyserEquation::states() const
153157
{
154158
return mPimpl->mStates;
155159
}
@@ -168,7 +172,7 @@ size_t AnalyserEquation::computedConstantCount() const
168172
return mPimpl->mComputedConstants.size();
169173
}
170174

171-
std::vector<AnalyserVariablePtr> AnalyserEquation::computedConstants() const
175+
const std::vector<AnalyserVariablePtr> &AnalyserEquation::computedConstants() const
172176
{
173177
return mPimpl->mComputedConstants;
174178
}
@@ -187,7 +191,7 @@ size_t AnalyserEquation::algebraicVariableCount() const
187191
return mPimpl->mAlgebraicVariables.size();
188192
}
189193

190-
std::vector<AnalyserVariablePtr> AnalyserEquation::algebraicVariables() const
194+
const std::vector<AnalyserVariablePtr> &AnalyserEquation::algebraicVariables() const
191195
{
192196
return mPimpl->mAlgebraicVariables;
193197
}
@@ -206,7 +210,7 @@ size_t AnalyserEquation::externalVariableCount() const
206210
return mPimpl->mExternalVariables.size();
207211
}
208212

209-
std::vector<AnalyserVariablePtr> AnalyserEquation::externalVariables() const
213+
const std::vector<AnalyserVariablePtr> &AnalyserEquation::externalVariables() const
210214
{
211215
return mPimpl->mExternalVariables;
212216
}

src/analyserequationast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ void AnalyserEquationAst::setType(Type type)
170170
mPimpl->mType = type;
171171
}
172172

173-
std::string AnalyserEquationAst::value() const
173+
const std::string &AnalyserEquationAst::value() const
174174
{
175175
return mPimpl->mValue;
176176
}

src/analyserexternalvariable.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ std::vector<VariablePtr>::iterator AnalyserExternalVariable::AnalyserExternalVar
3131
const std::string &componentName,
3232
const std::string &variableName)
3333
{
34-
return std::find_if(mDependencies.begin(), mDependencies.end(), [=](const auto &v) {
34+
return std::find_if(mDependencies.begin(), mDependencies.end(), [&](const auto &v) {
3535
return (owningModel(v) == model)
3636
&& (owningComponent(v)->name() == componentName)
3737
&& (v->name() == variableName);
@@ -40,7 +40,7 @@ std::vector<VariablePtr>::iterator AnalyserExternalVariable::AnalyserExternalVar
4040

4141
std::vector<VariablePtr>::iterator AnalyserExternalVariable::AnalyserExternalVariableImpl::findDependency(const VariablePtr &variable)
4242
{
43-
return std::find_if(mDependencies.begin(), mDependencies.end(), [=](const auto &v) {
43+
return std::find_if(mDependencies.begin(), mDependencies.end(), [&](const auto &v) {
4444
return v == variable;
4545
});
4646
}
@@ -155,7 +155,7 @@ VariablePtr AnalyserExternalVariable::dependency(const ModelPtr &model,
155155
nullptr;
156156
}
157157

158-
std::vector<VariablePtr> AnalyserExternalVariable::dependencies() const
158+
const std::vector<VariablePtr> &AnalyserExternalVariable::dependencies() const
159159
{
160160
return mPimpl->mDependencies;
161161
}

src/analysermodel.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ limitations under the License.
2323

2424
namespace libcellml {
2525

26+
static const std::vector<AnalyserEquationPtr> NO_ANALYSER_EQUATION;
27+
static const std::vector<AnalyserVariablePtr> NO_ANALYSER_VARIABLE;
28+
2629
AnalyserModelPtr AnalyserModel::AnalyserModelImpl::create(const ModelPtr &model)
2730
{
2831
return std::shared_ptr<AnalyserModel> {new AnalyserModel(model)};
@@ -104,10 +107,10 @@ size_t AnalyserModel::stateCount() const
104107
return mPimpl->mStates.size();
105108
}
106109

107-
std::vector<AnalyserVariablePtr> AnalyserModel::states() const
110+
const std::vector<AnalyserVariablePtr> &AnalyserModel::states() const
108111
{
109112
if (!isValid()) {
110-
return {};
113+
return NO_ANALYSER_VARIABLE;
111114
}
112115

113116
return mPimpl->mStates;
@@ -132,10 +135,10 @@ size_t AnalyserModel::constantCount() const
132135
return mPimpl->mConstants.size();
133136
}
134137

135-
std::vector<AnalyserVariablePtr> AnalyserModel::constants() const
138+
const std::vector<AnalyserVariablePtr> &AnalyserModel::constants() const
136139
{
137140
if (!isValid()) {
138-
return {};
141+
return NO_ANALYSER_VARIABLE;
139142
}
140143

141144
return mPimpl->mConstants;
@@ -159,10 +162,10 @@ size_t AnalyserModel::computedConstantCount() const
159162
return mPimpl->mComputedConstants.size();
160163
}
161164

162-
std::vector<AnalyserVariablePtr> AnalyserModel::computedConstants() const
165+
const std::vector<AnalyserVariablePtr> &AnalyserModel::computedConstants() const
163166
{
164167
if (!isValid()) {
165-
return {};
168+
return NO_ANALYSER_VARIABLE;
166169
}
167170

168171
return mPimpl->mComputedConstants;
@@ -186,10 +189,10 @@ size_t AnalyserModel::algebraicVariableCount() const
186189
return mPimpl->mAlgebraicVariables.size();
187190
}
188191

189-
std::vector<AnalyserVariablePtr> AnalyserModel::algebraicVariables() const
192+
const std::vector<AnalyserVariablePtr> &AnalyserModel::algebraicVariables() const
190193
{
191194
if (!isValid()) {
192-
return {};
195+
return NO_ANALYSER_VARIABLE;
193196
}
194197

195198
return mPimpl->mAlgebraicVariables;
@@ -213,10 +216,10 @@ size_t AnalyserModel::externalVariableCount() const
213216
return mPimpl->mExternalVariables.size();
214217
}
215218

216-
std::vector<AnalyserVariablePtr> AnalyserModel::externalVariables() const
219+
const std::vector<AnalyserVariablePtr> &AnalyserModel::externalVariables() const
217220
{
218221
if (!isValid()) {
219-
return {};
222+
return NO_ANALYSER_VARIABLE;
220223
}
221224

222225
return mPimpl->mExternalVariables;
@@ -237,8 +240,20 @@ AnalyserVariablePtr AnalyserModel::analyserVariable(const VariablePtr &variable)
237240
return {};
238241
}
239242

243+
// Check the cache first.
244+
245+
auto analyserVariableIt = mPimpl->mAnalyserVariables.find(variable.get());
246+
247+
if (analyserVariableIt != mPimpl->mAnalyserVariables.end()) {
248+
return analyserVariableIt->second;
249+
}
250+
251+
// Not in the cache, so do the equivalence-based search.
252+
240253
for (const auto &analyserVariable : analyserVariables(shared_from_this())) {
241254
if (areEquivalentVariables(variable, analyserVariable->variable())) {
255+
mPimpl->mAnalyserVariables.emplace(variable.get(), analyserVariable);
256+
242257
return analyserVariable;
243258
}
244259
}
@@ -255,10 +270,10 @@ size_t AnalyserModel::analyserEquationCount() const
255270
return mPimpl->mAnalyserEquations.size();
256271
}
257272

258-
std::vector<AnalyserEquationPtr> AnalyserModel::analyserEquations() const
273+
const std::vector<AnalyserEquationPtr> &AnalyserModel::analyserEquations() const
259274
{
260275
if (!isValid()) {
261-
return {};
276+
return NO_ANALYSER_EQUATION;
262277
}
263278

264279
return mPimpl->mAnalyserEquations;

src/analysermodel_p.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ struct AnalyserModel::AnalyserModelImpl
6666
}
6767
};
6868

69+
mutable std::unordered_map<Variable *, AnalyserVariablePtr> mAnalyserVariables;
70+
6971
struct VariableKeyPairHash
7072
{
7173
size_t operator()(const VariableKeyPair &pair) const

src/analyservariable.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ std::vector<AnalyserEquationPtr> AnalyserVariable::analyserEquations() const
120120

121121
std::vector<AnalyserEquationPtr> res;
122122

123+
res.reserve(mPimpl->mAnalyserEquations.size());
124+
123125
for (const auto &analyserEquation : mPimpl->mAnalyserEquations) {
124126
res.push_back(analyserEquation.lock());
125127
}

src/annotator.cpp

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
#include "libcellml/annotator.h"
1818

1919
#include <algorithm>
20+
#include <format>
2021
#include <sstream>
2122
#include <unordered_map>
2223

@@ -236,13 +237,16 @@ void Annotator::AnnotatorImpl::listComponentIdsAndItems(const ComponentPtr &comp
236237
if (idList.count(id) != 0) {
237238
// Get the range of items with this identifier:
238239
auto rangePair = idList.equal_range(id);
240+
auto compEquiv = owningComponent(equivalentVariable);
241+
auto compVar = owningComponent(variable);
239242
for (auto it = rangePair.first; it != rangePair.second; ++it) {
240243
// Make sure it's also a CONNECTION item.
241244
if (it->second->type() == CellmlElementType::CONNECTION) {
242245
auto testPair = it->second->variablePair();
243-
if ((owningComponent(testPair->variable1()) == owningComponent(equivalentVariable)) && (owningComponent(testPair->variable2()) == owningComponent(variable))) {
244-
found = true;
245-
} else if ((owningComponent(testPair->variable2()) == owningComponent(equivalentVariable)) && (owningComponent(testPair->variable1()) == owningComponent(variable))) {
246+
auto compTest1 = owningComponent(testPair->variable1());
247+
auto compTest2 = owningComponent(testPair->variable2());
248+
if (((compTest1 == compEquiv) && (compTest2 == compVar))
249+
|| ((compTest2 == compEquiv) && (compTest1 == compVar))) {
246250
found = true;
247251
}
248252
}
@@ -352,7 +356,7 @@ AnyCellmlElementPtr Annotator::AnnotatorImpl::convertToWeak(const AnyCellmlEleme
352356

353357
converted->mPimpl->mType = type;
354358

355-
switch (item->type()) {
359+
switch (type) {
356360
case CellmlElementType::COMPONENT:
357361
case CellmlElementType::COMPONENT_REF: {
358362
ComponentWeakPtr weakComponent = item->component();
@@ -517,7 +521,7 @@ void Annotator::AnnotatorImpl::addIssueInvalidArgument(CellmlElementType type)
517521
void Annotator::AnnotatorImpl::addIssueNonUnique(const std::string &id)
518522
{
519523
auto issue = Issue::IssueImpl::create();
520-
issue->mPimpl->setDescription("The identifier '" + id + "' occurs " + std::to_string(mIdList.count(id)) + " times in the model so a unique item cannot be located.");
524+
issue->mPimpl->setDescription("The identifier '" + id + "' occurs " + std::format("{}", mIdList.count(id)) + " times in the model so a unique item cannot be located.");
521525
issue->mPimpl->setLevel(Issue::Level::WARNING);
522526
issue->mPimpl->setReferenceRule(Issue::ReferenceRule::ANNOTATOR_ID_NOT_UNIQUE);
523527
addIssue(issue);
@@ -1417,20 +1421,26 @@ size_t Annotator::itemCount(const std::string &id)
14171421

14181422
void Annotator::AnnotatorImpl::doUpdateComponentHash(const ComponentPtr &component, std::string &idsString)
14191423
{
1420-
for (size_t i = 0; i < component->variableCount(); ++i) {
1421-
idsString += "v=" + std::to_string(i) + component->variable(i)->id();
1424+
const auto variableCount = component->variableCount();
1425+
const auto resetCount = component->resetCount();
1426+
const auto componentCount = component->componentCount();
1427+
1428+
idsString.reserve(idsString.size() + 24 * (variableCount + resetCount + componentCount));
1429+
1430+
for (size_t i = 0; i < variableCount; ++i) {
1431+
idsString += "v=" + std::format("{}", i) + component->variable(i)->id();
14221432
}
14231433

1424-
for (size_t i = 0; i < component->resetCount(); ++i) {
1434+
for (size_t i = 0; i < resetCount; ++i) {
14251435
auto reset = component->reset(i);
1426-
idsString += "r=" + std::to_string(i) + reset->id() + "rv=" + reset->resetValueId() + "tv=" + reset->testValueId();
1436+
idsString += "r=" + std::format("{}", i) + reset->id() + "rv=" + reset->resetValueId() + "tv=" + reset->testValueId();
14271437
}
14281438

14291439
// Note that MathML identifiers are not yet included.
14301440

1431-
for (size_t i = 0; i < component->componentCount(); ++i) {
1441+
for (size_t i = 0; i < componentCount; ++i) {
14321442
auto child = component->component(i);
1433-
idsString += "c=" + std::to_string(i) + child->id() + "ce=" + child->encapsulationId();
1443+
idsString += "c=" + std::format("{}", i) + child->id() + "ce=" + child->encapsulationId();
14341444
doUpdateComponentHash(child, idsString);
14351445
}
14361446
}
@@ -1443,26 +1453,27 @@ size_t Annotator::AnnotatorImpl::generateHash()
14431453
if (model != nullptr) {
14441454
std::string idsString;
14451455
size_t i;
1446-
idsString += "m=" + model->id() + "me=" + model->encapsulationId();
14471456

14481457
auto importSources = getAllImportSources(model);
1458+
idsString.reserve(64 + 32 * (importSources.size() + model->unitsCount() + model->componentCount()));
1459+
idsString += "m=" + model->id() + "me=" + model->encapsulationId();
14491460
i = 0;
14501461
for (auto &importSource : importSources) {
1451-
idsString += "i=" + std::to_string(++i) + importSource->id();
1462+
idsString += "i=" + std::format("{}", ++i) + importSource->id();
14521463
}
14531464

14541465
for (i = 0; i < model->unitsCount(); ++i) {
14551466
auto units = model->units(i);
1456-
idsString += "U=" + std::to_string(i) + units->id();
1467+
idsString += "U=" + std::format("{}", i) + units->id();
14571468
for (size_t j = 0; j < units->unitCount(); ++j) {
1458-
idsString += "u=" + std::to_string(j) + units->unitId(j);
1469+
idsString += "u=" + std::format("{}", j) + units->unitId(j);
14591470
}
14601471
}
14611472

14621473
for (i = 0; i < model->componentCount(); ++i) {
14631474
auto component = model->component(i);
1464-
idsString += "c=" + std::to_string(i) + component->id();
1465-
idsString += "cr=" + std::to_string(i) + component->encapsulationId();
1475+
idsString += "c=" + std::format("{}", i) + component->id();
1476+
idsString += "cr=" + std::format("{}", i) + component->encapsulationId();
14661477
doUpdateComponentHash(component, idsString);
14671478
}
14681479

0 commit comments

Comments
 (0)