Skip to content

Commit 403d96a

Browse files
arjo129Addisu Z. Taddese
andauthored
Introduce a cache to improve performance of construction of SDFormat (#1610)
Reduces load times significantly as it caches the first parse of the spec so that it does not need to be reparsed during construction through static initiallization of a cache. --------- Signed-off-by: Arjo Chakravarty <arjo@openrobotics.org> Signed-off-by: Arjo Chakravarty <arjo129@gmail.com> Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
1 parent 9c1bd31 commit 403d96a

5 files changed

Lines changed: 73 additions & 3 deletions

File tree

include/sdf/SDFImpl.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ namespace sdf
166166
class SDFORMAT_VISIBLE SDF
167167
{
168168
public: SDF();
169+
public: SDF(const SDF& other);
170+
public: SDF& operator=(const SDF& other);
169171
/// \brief Destructor
170172
public: ~SDF();
171173
public: void PrintDescription();

src/Root.cc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*
1616
*/
17+
#include <gz/utils/NeverDestroyed.hh>
1718
#include <string>
1819
#include <variant>
1920
#include <vector>
@@ -24,6 +25,7 @@
2425
#include "sdf/Light.hh"
2526
#include "sdf/Model.hh"
2627
#include "sdf/Root.hh"
28+
#include "sdf/SDFImpl.hh"
2729
#include "sdf/Types.hh"
2830
#include "sdf/World.hh"
2931
#include "sdf/parser.hh"
@@ -34,6 +36,18 @@
3436

3537
using namespace sdf;
3638

39+
/// \brief A cache for SDF Parsing
40+
struct SdfCache {
41+
42+
/// \brief Constructor.
43+
SdfCache(): sdfParsed(new SDF()) {
44+
init(this->sdfParsed);
45+
}
46+
47+
/// \brief The parsed SDF Spec
48+
SDFPtr sdfParsed;
49+
};
50+
3751
/// \brief Private data for sdf::Root
3852
class sdf::Root::Implementation
3953
{
@@ -217,9 +231,9 @@ Errors Root::LoadSdfString(const std::string &_sdf)
217231
Errors Root::LoadSdfString(const std::string &_sdf, const ParserConfig &_config)
218232
{
219233
Errors errors;
220-
SDFPtr sdfParsed(new SDF());
221-
init(sdfParsed);
222-
234+
// Make a copy of the cached structure
235+
static gz::utils::NeverDestroyed<SdfCache> cache;
236+
SDFPtr sdfParsed = std::make_shared<SDF>(*cache.Access().sdfParsed);
223237
// Read an SDF string, and store the result in sdfParsed.
224238
if (!readString(_sdf, _config, sdfParsed, errors))
225239
{

src/SDF.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,18 @@ SDF::SDF()
219219
{
220220
}
221221

222+
/////////////////////////////////////////////////
223+
SDF::SDF(const SDF& other)
224+
{
225+
this->dataPtr = std::make_unique<SDFPrivate>(*other.dataPtr);
226+
}
227+
228+
/////////////////////////////////////////////////
229+
SDF& SDF::operator=(const SDF& other)
230+
{
231+
this->dataPtr = std::make_unique<SDFPrivate>(*other.dataPtr);
232+
return *this;
233+
}
222234
/////////////////////////////////////////////////
223235
SDF::~SDF()
224236
{

src/SDFImplPrivate.hh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ namespace sdf
3737
{
3838
};
3939

40+
/// Copy constructor: Ensure Deep copy.
41+
public: SDFPrivate(const SDFPrivate& other)
42+
{
43+
this->path = other.path;
44+
this->originalVersion = other.originalVersion;
45+
this->root = other.root->Clone();
46+
}
47+
48+
/// Copy constructor: Ensure Deep Copy
49+
public: SDFPrivate& operator=(const SDFPrivate& other)
50+
{
51+
this->path = other.path;
52+
this->originalVersion = other.originalVersion;
53+
this->root = other.root->Clone();
54+
return *this;
55+
}
56+
4057
/// \brief Store the root element.
4158
/// \sa ElementPtr Root()
4259
/// \sa void Root(const ElementPtr _root)

src/SDF_TEST.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -854,4 +854,29 @@ TEST(SDF, FindFileModelSDFCurrDir)
854854
ASSERT_EQ(std::remove(tempFile.c_str()), 0);
855855
std::filesystem::current_path(prevPath);
856856
}
857+
858+
///////////////////////////////////////////////////
859+
// Test the copy constructor provides a deep copy
860+
TEST(SDF, CopyConstructor)
861+
{
862+
// Set up a simple sdf model file
863+
std::ostringstream stream;
864+
stream << "<sdf version='1.3'>"
865+
<< " <model name='test_model'>"
866+
<< " <pose>0 1 2 0 0 0</pose>"
867+
<< " <static>false</static>"
868+
<< " </model>"
869+
<< "</sdf>";
870+
sdf::SDF sdfParsed;
871+
sdfParsed.SetFromString(stream.str());
872+
873+
sdf::SDF copy1sdfParsed(sdfParsed);
874+
sdf::SDF copy2sdfParsed = sdfParsed;
875+
876+
sdfParsed.Root()->SetName("Test");
877+
ASSERT_EQ(sdfParsed.Root()->GetName(), "Test");
878+
// Since a deep copy occurs no changes should be reflected;
879+
ASSERT_NE(copy1sdfParsed.Root()->GetName(), "Test");
880+
ASSERT_NE(copy2sdfParsed.Root()->GetName(), "Test");
881+
}
857882
#endif // _WIN32

0 commit comments

Comments
 (0)