From 29c658d6520deaeec750464ad85d7e0c065b79cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Barv=C3=AD=C5=99?= Date: Sat, 19 Apr 2025 02:06:39 +0200 Subject: [PATCH 1/2] Remove multiple allocation caused by push_back in Extrude method --- .../geometry/operations/geometryutils.h | 54 +++++++++++++------ src/cpp/web-ifc/parsing/IfcTokenChunk.cpp | 25 --------- src/cpp/web-ifc/parsing/IfcTokenStream.cpp | 5 -- src/cpp/web-ifc/parsing/IfcTokenStream.h | 18 ++++--- 4 files changed, 49 insertions(+), 53 deletions(-) diff --git a/src/cpp/web-ifc/geometry/operations/geometryutils.h b/src/cpp/web-ifc/geometry/operations/geometryutils.h index 57ba7c5e6..f04eda6f9 100644 --- a/src/cpp/web-ifc/geometry/operations/geometryutils.h +++ b/src/cpp/web-ifc/geometry/operations/geometryutils.h @@ -9,6 +9,7 @@ #endif #include +#include #include #include "../representation/geometry.h" #include "../representation/IfcGeometry.h" @@ -826,7 +827,6 @@ namespace webifc::geometry { spdlog::debug("[Extrude({})]"); IfcGeometry geom; - std::vector holesIndicesHash; // check if first point is equal to last point, otherwise the outer loop of the shape is not closed glm::dvec3 lastToFirstPoint = profile.curve.points.front() - profile.curve.points.back(); @@ -834,11 +834,33 @@ namespace webifc::geometry profile.curve.points.push_back(profile.curve.points.front()); } + const size_t nofHolePoints = std::reduce( + profile.holes.begin(), + profile.holes.end(), + 0, + [](size_t acc, auto& hole) { return acc + hole.points.size(); } + ); + std::vector holesIndicesHash(profile.curve.points.size() + nofHolePoints, false); + auto holesIndicesHashCursor = profile.curve.points.size(); + + // Reservation space for geometry + { + const auto currentSize = geom.vertexData.size(); + const auto profilePointSize = profile.curve.points.size() * 6; + const auto holesPointSize = nofHolePoints * 6; + const auto addedPointsToProfile = (profile.curve.points.size() + nofHolePoints) * 6; + geom.vertexData.reserve(currentSize + profilePointSize + holesPointSize + addedPointsToProfile); + } + // build the caps { using Point = std::array; int polygonCount = 1 + profile.holes.size(); // Main profile + holes std::vector> polygon(polygonCount); + for (size_t i = 0; i < polygonCount; i++) { + if (i == 0) { polygon[i].reserve(profile.curve.points.size()); } + else { polygon[i].reserve(profile.holes[i - 1].points.size()); } + } glm::dvec3 normal = dir; @@ -851,19 +873,13 @@ namespace webifc::geometry polygon[0].push_back({pt.x, pt.y}); } - for (size_t i = 0; i < profile.curve.points.size(); i++) - { - holesIndicesHash.push_back(false); - } - for (size_t i = 0; i < profile.holes.size(); i++) { IfcCurve hole = profile.holes[i]; - int pointCount = hole.points.size(); - for (int j = 0; j < pointCount; j++) + for (int j = 0; j < hole.points.size(); j++) { - holesIndicesHash.push_back(j == 0); + holesIndicesHash[holesIndicesHashCursor++] = j == 0; glm::dvec2 pt = hole.points[j]; glm::dvec4 et = glm::dvec4(glm::dvec3(pt, 0) + dir * distance, 1); @@ -876,6 +892,17 @@ namespace webifc::geometry std::vector indices = mapbox::earcut(polygon); + // Reservation space for faces + { + const auto currrentIndiciesSize = geom.indexData.size(); + const auto nofIndices = indices.size() * 2; + const auto capIndicies = (profile.curve.points.size() - 1 - profile.holes.size()) * 6; + geom.indexData.reserve(currrentIndiciesSize + nofIndices + capIndicies); + + const auto currentFaceSize = geom.planeData.size(); + geom.planeData.reserve(currentFaceSize + (nofIndices + capIndicies) / 3); + } + if (indices.size() < 3) { // probably a degenerate polygon @@ -960,13 +987,8 @@ namespace webifc::geometry uint32_t tr = capSize + i - 0; // this winding should be correct - geom.AddFace(geom.GetPoint(tl), - geom.GetPoint(br), - geom.GetPoint(bl)); - - geom.AddFace(geom.GetPoint(tl), - geom.GetPoint(tr), - geom.GetPoint(br)); + geom.AddFace(tl, br, bl); + geom.AddFace(tl, tr, br); } return geom; diff --git a/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp b/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp index 2aa797dd0..e3c208210 100644 --- a/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp +++ b/src/cpp/web-ifc/parsing/IfcTokenChunk.cpp @@ -24,31 +24,6 @@ namespace webifc::parsing return true; } - bool IfcTokenStream::IfcTokenChunk::Clear() - { - return Clear(false); - } - - size_t IfcTokenStream::IfcTokenChunk::GetTokenRef() - { - return _startRef; - } - - size_t IfcTokenStream::IfcTokenChunk::TokenSize() - { - return _currentSize; - } - - bool IfcTokenStream::IfcTokenChunk::IsLoaded() - { - return _loaded; - } - - size_t IfcTokenStream::IfcTokenChunk::GetMaxSize() - { - return _chunkSize; - } - std::string_view IfcTokenStream::IfcTokenChunk::ReadString(const size_t ptr,const size_t size) { if (!_loaded) Load(); diff --git a/src/cpp/web-ifc/parsing/IfcTokenStream.cpp b/src/cpp/web-ifc/parsing/IfcTokenStream.cpp index 6c28a8dd9..b04fc1afa 100644 --- a/src/cpp/web-ifc/parsing/IfcTokenStream.cpp +++ b/src/cpp/web-ifc/parsing/IfcTokenStream.cpp @@ -149,11 +149,6 @@ namespace webifc::parsing _readPtr--; } - bool IfcTokenStream::IsAtEnd() - { - return _currentChunk >= _chunks.size()-1 && _readPtr >= _chunks.back().TokenSize(); - } - size_t IfcTokenStream::GetReadOffset() { return _cChunk->GetTokenRef() + _readPtr; diff --git a/src/cpp/web-ifc/parsing/IfcTokenStream.h b/src/cpp/web-ifc/parsing/IfcTokenStream.h index 98ac9580d..d353fc9fc 100644 --- a/src/cpp/web-ifc/parsing/IfcTokenStream.h +++ b/src/cpp/web-ifc/parsing/IfcTokenStream.h @@ -56,7 +56,9 @@ namespace webifc::parsing void Forward(const size_t size); std::string_view ReadString(); void Back(); - bool IsAtEnd(); + inline bool IsAtEnd() const noexcept { + return _currentChunk >= _chunks.size() - 1 && _readPtr >= _chunks.back().TokenSize(); + }; void MoveTo(const size_t pos); size_t GetReadOffset(); size_t GetTotalSize(); @@ -95,14 +97,16 @@ namespace webifc::parsing class IfcTokenChunk { public: - IfcTokenChunk(const size_t chunkSize, const size_t startRef, const size_t fileStartRef, IfcFileStream *_fileStream); + IfcTokenChunk(const size_t chunkSize, const size_t startRef, const size_t fileStartRef, IfcFileStream *_fileStream); bool Clear(bool force); - bool Clear(); - bool IsLoaded(); - size_t TokenSize(); - size_t GetTokenRef(); + bool Clear() { return Clear(false); } + inline bool IsLoaded() const noexcept { return _loaded; } + inline size_t TokenSize() const noexcept { return _currentSize; } + inline size_t GetTokenRef() const noexcept { return _startRef; } + size_t GetMaxSize() const noexcept { return _chunkSize; } + void Push(void *v, const size_t size); - size_t GetMaxSize(); + std::string_view ReadString(const size_t ptr,const size_t size); template T Read(const size_t ptr) { From 7e5f80235de5e895ddb92caba0d023f264c9b268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Barv=C3=AD=C5=99?= Date: Sat, 19 Apr 2025 02:10:35 +0200 Subject: [PATCH 2/2] Remove std::reduce --- src/cpp/web-ifc/geometry/operations/geometryutils.h | 11 ++++------- src/cpp/web-ifc/parsing/IfcTokenStream.h | 4 ++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/cpp/web-ifc/geometry/operations/geometryutils.h b/src/cpp/web-ifc/geometry/operations/geometryutils.h index f04eda6f9..48e18ccaa 100644 --- a/src/cpp/web-ifc/geometry/operations/geometryutils.h +++ b/src/cpp/web-ifc/geometry/operations/geometryutils.h @@ -9,7 +9,6 @@ #endif #include -#include #include #include "../representation/geometry.h" #include "../representation/IfcGeometry.h" @@ -834,12 +833,10 @@ namespace webifc::geometry profile.curve.points.push_back(profile.curve.points.front()); } - const size_t nofHolePoints = std::reduce( - profile.holes.begin(), - profile.holes.end(), - 0, - [](size_t acc, auto& hole) { return acc + hole.points.size(); } - ); + size_t nofHolePoints = 0; + for (const auto &hole : profile.holes) { + nofHolePoints += hole.points.size(); + }; std::vector holesIndicesHash(profile.curve.points.size() + nofHolePoints, false); auto holesIndicesHashCursor = profile.curve.points.size(); diff --git a/src/cpp/web-ifc/parsing/IfcTokenStream.h b/src/cpp/web-ifc/parsing/IfcTokenStream.h index d353fc9fc..4b1dac247 100644 --- a/src/cpp/web-ifc/parsing/IfcTokenStream.h +++ b/src/cpp/web-ifc/parsing/IfcTokenStream.h @@ -99,11 +99,11 @@ namespace webifc::parsing public: IfcTokenChunk(const size_t chunkSize, const size_t startRef, const size_t fileStartRef, IfcFileStream *_fileStream); bool Clear(bool force); - bool Clear() { return Clear(false); } + inline bool Clear() { return Clear(false); } inline bool IsLoaded() const noexcept { return _loaded; } inline size_t TokenSize() const noexcept { return _currentSize; } inline size_t GetTokenRef() const noexcept { return _startRef; } - size_t GetMaxSize() const noexcept { return _chunkSize; } + inline size_t GetMaxSize() const noexcept { return _chunkSize; } void Push(void *v, const size_t size);