Skip to content

Commit c540f31

Browse files
authored
Modeling - Improve memory management in BOPAlgo_PaveFiller::MakeBlocks (#1044)
This change improves allocator usage in Boolean operations to reduce memory accumulation and make allocator choices explicit. BOPAlgo_PaveFiller_6.cxx: - Add aDefaultAllocator for collections requiring proper Free() behavior - aMVTol, aLPB, aDMVLV now use default allocator (have Remove/UnBind ops) - aMPBCommon now uses aTmpAllocator (was missing allocator) - Cross-iteration collections now explicitly use aAllocator - Add comments explaining allocator choice rationale BOPDS_DS.cxx: - SubShapesOnIn() now uses const references instead of copying 4 IndexedMaps - This eliminates unnecessary memory allocations per face-face intersection
1 parent 6606bc7 commit c540f31

2 files changed

Lines changed: 79 additions & 55 deletions

File tree

src/ModelingAlgorithms/TKBO/BOPAlgo/BOPAlgo_PaveFiller_6.cxx

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -660,45 +660,59 @@ void BOPAlgo_PaveFiller::MakeBlocks(const Message_ProgressRange& theRange)
660660
return;
661661
}
662662
//
663-
bool bExist, bValid2D;
664-
int i, nF1, nF2, aNbC, aNbP, j;
665-
int nV1, nV2;
666-
double aT1, aT2;
663+
bool bExist, bValid2D;
664+
int i, nF1, nF2, aNbC, aNbP, j;
665+
int nV1, nV2;
666+
double aT1, aT2;
667+
// Main allocator for cross-iteration data (IncAllocator for performance)
667668
occ::handle<NCollection_BaseAllocator> aAllocator = new NCollection_IncAllocator;
668669
// Temporary allocator for per-iteration collections that are cleared each iteration.
669-
// Using separate allocator allows to reclaim memory via Reset(false) at the start
670-
// of each iteration, preventing memory accumulation in the main loop.
670+
// Using separate allocator allows memory reuse via Reset(false) at each iteration.
671+
// Collections are kept outside the loop to reuse their bucket arrays after Clear().
671672
occ::handle<NCollection_IncAllocator> aTmpAllocator = new NCollection_IncAllocator;
673+
// Default allocator for collections that require proper Free() behavior (Remove/UnBind).
674+
// IncAllocator::Free() is a no-op, so collections with Remove/UnBind must use default.
675+
occ::handle<NCollection_BaseAllocator> aDefaultAllocator =
676+
NCollection_BaseAllocator::CommonBaseAllocator();
672677
NCollection_List<occ::handle<BOPDS_PaveBlock>>::Iterator aItLPB;
673678
TopoDS_Edge aES;
674679
occ::handle<BOPDS_PaveBlock> aPBOut;
675680
//
676681
//-----------------------------------------------------scope f
677682
//
678-
// Per-iteration collections (use temporary allocator, reset each iteration)
679-
NCollection_List<int> aLSE(aTmpAllocator), aLBV(aTmpAllocator);
680-
NCollection_Map<int> aMVOnIn(100, aTmpAllocator), aMVCommon(100, aTmpAllocator),
681-
aMVStick(100, aTmpAllocator), aMVEF(100, aTmpAllocator), aMVBounds(100, aTmpAllocator);
683+
// Per-iteration collections (use temporary allocator, cleared and reset each iteration).
684+
// Kept outside loop to reuse bucket arrays - Clear() preserves allocated buckets.
685+
NCollection_List<int> aLSE(aTmpAllocator);
686+
NCollection_List<int> aLBV(aTmpAllocator);
687+
NCollection_Map<int> aMVOnIn(100, aTmpAllocator);
688+
NCollection_Map<int> aMVCommon(100, aTmpAllocator);
689+
NCollection_Map<int> aMVStick(100, aTmpAllocator);
690+
NCollection_Map<int> aMVEF(100, aTmpAllocator);
691+
NCollection_Map<int> aMVBounds(100, aTmpAllocator);
692+
NCollection_Map<int> aMI(100, aTmpAllocator);
682693
NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>> aMPBOnIn(100, aTmpAllocator);
683-
NCollection_Map<occ::handle<BOPDS_PaveBlock>> aMPBCommon;
684-
NCollection_DataMap<int, double> aMVTol(100, aTmpAllocator);
694+
NCollection_Map<occ::handle<BOPDS_PaveBlock>> aMPBCommon(100, aTmpAllocator);
685695
NCollection_DataMap<int, NCollection_List<int>> aDMBV(100, aTmpAllocator);
696+
// aMVTol has UnBind() operations - must use default allocator for proper Free()
697+
NCollection_DataMap<int, double> aMVTol(100, aDefaultAllocator);
698+
//
686699
// Cross-iteration collections (use main allocator, persist through entire loop)
687-
NCollection_Map<int> aMI(100, aAllocator);
688-
NCollection_Map<occ::handle<BOPDS_PaveBlock>> aMPBAdd(100, aAllocator);
689-
NCollection_List<occ::handle<BOPDS_PaveBlock>> aLPB(aAllocator);
700+
NCollection_Map<occ::handle<BOPDS_PaveBlock>> aMPBAdd(100, aAllocator);
701+
// aLPB has Remove() operations - must use default allocator for proper Free()
702+
NCollection_List<occ::handle<BOPDS_PaveBlock>> aLPB(aDefaultAllocator);
690703
NCollection_IndexedDataMap<TopoDS_Shape, BOPDS_CoupleOfPaveBlocks, TopTools_ShapeMapHasher>
691704
aMSCPB(100, aAllocator);
692705
NCollection_DataMap<TopoDS_Shape, int, TopTools_ShapeMapHasher> aMVI(100, aAllocator);
693706
NCollection_DataMap<occ::handle<BOPDS_PaveBlock>, NCollection_List<occ::handle<BOPDS_PaveBlock>>>
694-
aDMExEdges(100, aAllocator);
695-
NCollection_DataMap<int, int> aDMNewSD(100, aAllocator);
696-
NCollection_DataMap<int, NCollection_List<int>> aDMVLV;
707+
aDMExEdges(100, aAllocator);
708+
NCollection_DataMap<int, int> aDMNewSD(100, aAllocator);
709+
// aDMVLV has UnBind() operations - must use default allocator for proper Free()
710+
NCollection_DataMap<int, NCollection_List<int>> aDMVLV(100, aDefaultAllocator);
697711
NCollection_DataMap<int, double>::Iterator aItMV;
698712
NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>> aMicroPB(100, aAllocator);
699-
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> aVertsOnRejectedPB;
713+
NCollection_IndexedMap<TopoDS_Shape, TopTools_ShapeMapHasher> aVertsOnRejectedPB(100, aAllocator);
700714
// Map of PaveBlocks with the faces to which it has to be added
701-
BOPAlgo_DataMapOfPaveBlockListOfInteger aPBFacesMap;
715+
BOPAlgo_DataMapOfPaveBlockListOfInteger aPBFacesMap(100, aAllocator);
702716
//
703717
// The vector aFFToRecheck contains indices of potentially problematic Face-Face intersections
704718
NCollection_Vector<int> aFFToRecheck;
@@ -736,6 +750,7 @@ void BOPAlgo_PaveFiller::MakeBlocks(const Message_ProgressRange& theRange)
736750
BOPDS_FaceInfo& aFI1 = myDS->ChangeFaceInfo(nF1);
737751
BOPDS_FaceInfo& aFI2 = myDS->ChangeFaceInfo(nF2);
738752
//
753+
// Clear per-iteration collections and reset allocator for memory reuse
739754
aMVOnIn.Clear();
740755
aMVCommon.Clear();
741756
aMPBOnIn.Clear();
@@ -747,6 +762,7 @@ void BOPAlgo_PaveFiller::MakeBlocks(const Message_ProgressRange& theRange)
747762
aMVStick.Clear();
748763
aMVEF.Clear();
749764
aMVBounds.Clear();
765+
aMI.Clear();
750766
aTmpAllocator->Reset(false);
751767
//
752768
myDS->SubShapesOnIn(nF1, nF2, aMVOnIn, aMVCommon, aMPBOnIn, aMPBCommon);
@@ -1104,15 +1120,6 @@ void BOPAlgo_PaveFiller::MakeBlocks(const Message_ProgressRange& theRange)
11041120
// into all faces, not participated in creation of that edge, as IN edge
11051121

11061122
PutSEInOtherFaces(aPSOuter.Next());
1107-
//
1108-
//-----------------------------------------------------scope t
1109-
aMVStick.Clear();
1110-
aMPBOnIn.Clear();
1111-
aMVOnIn.Clear();
1112-
aMVCommon.Clear();
1113-
aDMExEdges.Clear();
1114-
aMI.Clear();
1115-
aDMNewSD.Clear();
11161123
}
11171124

11181125
//=================================================================================================

src/ModelingAlgorithms/TKBO/BOPDS/BOPDS_DS.cxx

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,38 +1067,55 @@ void BOPDS_DS::SubShapesOnIn(
10671067
NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>>& thePBOnIn,
10681068
NCollection_Map<occ::handle<BOPDS_PaveBlock>>& theCommonPaveBlocks) const
10691069
{
1070+
const BOPDS_FaceInfo& aFaceInfo1 = FaceInfo(theFaceIndex1);
1071+
const BOPDS_FaceInfo& aFaceInfo2 = FaceInfo(theFaceIndex2);
1072+
1073+
// Use const references to avoid copying large IndexedMaps.
1074+
// Previous implementation copied 4 maps per call, causing significant memory overhead.
1075+
const NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>>& aPBOn1 = aFaceInfo1.PaveBlocksOn();
1076+
const NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>>& aPBIn1 = aFaceInfo1.PaveBlocksIn();
1077+
const NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>>& aPBOn2 = aFaceInfo2.PaveBlocksOn();
1078+
const NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>>& aPBIn2 = aFaceInfo2.PaveBlocksIn();
1079+
1080+
// Helper lambda to process pave blocks from a map
1081+
auto processMap =
1082+
[&thePBOnIn, &theMVOnIn](const NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>>& theMap) {
1083+
for (int anIdx = 1; anIdx <= theMap.Size(); ++anIdx)
1084+
{
1085+
const occ::handle<BOPDS_PaveBlock>& aPaveBlock = theMap(anIdx);
1086+
thePBOnIn.Add(aPaveBlock);
1087+
int aV1, aV2;
1088+
aPaveBlock->Indices(aV1, aV2);
1089+
theMVOnIn.Add(aV1);
1090+
theMVOnIn.Add(aV2);
1091+
}
1092+
};
10701093

1071-
const BOPDS_FaceInfo& aFaceInfo1 = FaceInfo(theFaceIndex1);
1072-
const BOPDS_FaceInfo& aFaceInfo2 = FaceInfo(theFaceIndex2);
1073-
NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>> pMPB[4];
1074-
pMPB[0] = aFaceInfo1.PaveBlocksOn();
1075-
pMPB[1] = aFaceInfo1.PaveBlocksIn();
1076-
pMPB[2] = aFaceInfo2.PaveBlocksOn();
1077-
pMPB[3] = aFaceInfo2.PaveBlocksIn();
1094+
// Process all four maps
1095+
processMap(aPBOn1);
1096+
processMap(aPBIn1);
1097+
processMap(aPBOn2);
1098+
processMap(aPBIn2);
10781099

1079-
for (int i = 0; i < 4; ++i)
1080-
{
1081-
for (int j = 1; j <= pMPB[i].Size(); ++j)
1100+
// Find common pave blocks (those in Face1 that are also in Face2)
1101+
auto findCommon = [&theCommonPaveBlocks, &theMVCommon, &aPBOn2, &aPBIn2](
1102+
const NCollection_IndexedMap<occ::handle<BOPDS_PaveBlock>>& theMap) {
1103+
for (int anIdx = 1; anIdx <= theMap.Size(); ++anIdx)
10821104
{
1083-
const occ::handle<BOPDS_PaveBlock>& aPaveBlock = pMPB[i](j);
1084-
thePBOnIn.Add(aPaveBlock);
1085-
int nV1, nV2;
1086-
aPaveBlock->Indices(nV1, nV2);
1087-
1088-
theMVOnIn.Add(nV1);
1089-
theMVOnIn.Add(nV2);
1090-
1091-
if (i < 2)
1105+
const occ::handle<BOPDS_PaveBlock>& aPaveBlock = theMap(anIdx);
1106+
if (aPBOn2.Contains(aPaveBlock) || aPBIn2.Contains(aPaveBlock))
10921107
{
1093-
if (pMPB[2].Contains(aPaveBlock) || pMPB[3].Contains(aPaveBlock))
1094-
{
1095-
theCommonPaveBlocks.Add(aPaveBlock);
1096-
theMVCommon.Add(nV1);
1097-
theMVCommon.Add(nV2);
1098-
}
1108+
theCommonPaveBlocks.Add(aPaveBlock);
1109+
int aV1, aV2;
1110+
aPaveBlock->Indices(aV1, aV2);
1111+
theMVCommon.Add(aV1);
1112+
theMVCommon.Add(aV2);
10991113
}
11001114
}
1101-
}
1115+
};
1116+
1117+
findCommon(aPBOn1);
1118+
findCommon(aPBIn1);
11021119

11031120
const NCollection_Map<int>& aMVOn1 = aFaceInfo1.VerticesOn();
11041121
const NCollection_Map<int>& aMVIn1 = aFaceInfo1.VerticesIn();

0 commit comments

Comments
 (0)