1 // File: NCollection_BaseAllocator.cxx
2 // Created: Fri Apr 12 12:53:28 2002
3 // Author: Alexander KARTOMIN (akm)
4 // <a-kartomin@opencascade.com>
5 // Purpose: Implementation of the BaseAllocator class
7 #include <NCollection_BaseAllocator.hxx>
8 #include <NCollection_DataMap.hxx>
9 #include <NCollection_Map.hxx>
10 #include <NCollection_List.hxx>
11 #include <Standard_Mutex.hxx>
13 IMPLEMENT_STANDARD_HANDLE(NCollection_BaseAllocator,MMgt_TShared)
14 IMPLEMENT_STANDARD_RTTIEXT(NCollection_BaseAllocator,MMgt_TShared)
16 //=======================================================================
18 //purpose : Standard allocation
19 //=======================================================================
21 void* NCollection_BaseAllocator::Allocate(const size_t size)
23 return Standard::Allocate(size);
26 //=======================================================================
28 //purpose : Standard deallocation
29 //=======================================================================
31 void NCollection_BaseAllocator::Free(void *anAddress)
33 if (anAddress) Standard::Free((Standard_Address&)anAddress);
36 //=======================================================================
37 //function : CommonBaseAllocator
38 //purpose : Creates the only one BaseAllocator
39 //=======================================================================
41 const Handle(NCollection_BaseAllocator)&
42 NCollection_BaseAllocator::CommonBaseAllocator(void)
44 static Handle(NCollection_BaseAllocator) pAllocator =
45 new NCollection_BaseAllocator;
49 // global variable to ensure that allocator will be created during loading the library
50 static Handle(NCollection_BaseAllocator) theAllocInit =
51 NCollection_BaseAllocator::CommonBaseAllocator();
53 //=======================================================================
55 * Structure for collecting statistics about blocks of one size
57 //=======================================================================
60 Standard_Size roundSize;
64 : roundSize(0), nbAlloc(0), nbFree(0) {}
65 StorageInfo(Standard_Size theSize)
66 : roundSize(theSize), nbAlloc(0), nbFree(0) {}
69 //=======================================================================
71 * Static data map (block_size -> StorageInfo)
73 //=======================================================================
74 static NCollection_DataMap<Standard_Size, StorageInfo>& StorageMap()
76 static NCollection_IncAllocator TheAlloc;
77 static NCollection_DataMap<Standard_Size, StorageInfo>
78 TheMap (1, & TheAlloc);
82 //=======================================================================
84 * Static data map (address -> AllocationID)
86 //=======================================================================
87 static NCollection_DataMap<Standard_Address, Standard_Size>& StorageIDMap()
89 static NCollection_IncAllocator TheAlloc;
90 static NCollection_DataMap<Standard_Address, Standard_Size>
91 TheMap (1, & TheAlloc);
95 //=======================================================================
97 * Static map (AllocationID)
99 //=======================================================================
100 static NCollection_Map<Standard_Size>& StorageIDSet()
102 static NCollection_IncAllocator TheAlloc;
103 static NCollection_Map<Standard_Size> TheMap (1, & TheAlloc);
107 //=======================================================================
109 * Exported value to set the block size for which it is required
110 * collecting alive allocation IDs.
111 * The method NCollection_BaseAllocator::PrintMemUsageStatistics
112 * dumps all alive IDs into the file alive.d in the current directory.
114 //=======================================================================
115 Standard_EXPORT Standard_Size& StandardCallBack_CatchSize()
117 static Standard_Size Value = 0;
121 //=======================================================================
123 * Exported value to set the allocation ID for which it is required
124 * to set a breakpoint on the moment of allocation or freeing.
125 * See the method NCollection_BaseAllocator::StandardCallBack
126 * where the value StandardCallBack_CatchID() is compared to the current ID.
127 * There you can place a break point at the stub assignment statement "a =".
129 //=======================================================================
130 Standard_EXPORT Standard_Size& StandardCallBack_CatchID()
132 static Standard_Size Value = 0;
136 //=======================================================================
138 * Static value of the current allocation ID. It provides unique
139 * numbering of allocation events.
141 //=======================================================================
142 static Standard_Size CurrentID = 0;
144 //=======================================================================
146 * Exported function to reset the callback system to the initial state
148 //=======================================================================
149 Standard_EXPORT void StandardCallBack_Reset()
151 StorageMap().Clear();
152 StorageIDMap().Clear();
153 StorageIDSet().Clear();
155 StandardCallBack_CatchSize() = 0;
156 StandardCallBack_CatchID() = 0;
159 //=======================================================================
160 //function : StandardCallBack
161 //purpose : Callback function to register alloc/free calls
162 //=======================================================================
164 void NCollection_BaseAllocator::StandardCallBack
165 (const Standard_Boolean theIsAlloc,
166 const Standard_Address theStorage,
167 const Standard_Size theRoundSize,
168 const Standard_Size /*theSize*/)
170 static Standard_Mutex aMutex;
171 Standard_Boolean isReentrant = Standard::IsReentrant();
174 // statistics by storage size
175 NCollection_DataMap<Standard_Size, StorageInfo>& aStMap = StorageMap();
176 if (!aStMap.IsBound(theRoundSize))
178 StorageInfo aEmpty(theRoundSize);
179 aStMap.Bind(theRoundSize, aEmpty);
181 StorageInfo& aInfo = aStMap(theRoundSize);
187 if (theRoundSize == StandardCallBack_CatchSize())
189 // statistics by alive objects
190 NCollection_DataMap<Standard_Address, Standard_Size>& aStIDMap = StorageIDMap();
191 NCollection_Map<Standard_Size>& aStIDSet = StorageIDSet();
195 aStIDMap.Bind(theStorage, ++CurrentID);
196 aStIDSet.Add(CurrentID);
197 if (CurrentID == StandardCallBack_CatchID())
199 // Place for break point for allocation of investigated ID
205 if (aStIDMap.IsBound(theStorage))
207 Standard_Size anID = aStIDMap(theStorage);
208 aStIDSet.Remove(anID);
209 if (anID == StandardCallBack_CatchID())
211 // Place for break point for freeing of investigated ID
222 //=======================================================================
223 //function : PrintMemUsageStatistics
224 //purpose : Prints memory usage statistics cumulated by StandardCallBack
225 //=======================================================================
227 void NCollection_BaseAllocator::PrintMemUsageStatistics()
230 NCollection_List<StorageInfo> aColl;
231 NCollection_List<StorageInfo>::Iterator itLst;
232 NCollection_DataMap<Standard_Size, StorageInfo>::Iterator itMap(StorageMap());
233 for (; itMap.More(); itMap.Next())
235 for (itLst.Init(aColl); itLst.More(); itLst.Next())
236 if (itMap.Value().roundSize < itLst.Value().roundSize)
239 aColl.InsertBefore(itMap.Value(), itLst);
241 aColl.Append(itMap.Value());
243 Standard_Size aTotAlloc = 0;
244 Standard_Size aTotLeft = 0;
246 FILE * ff = fopen("memstat.d", "wt");
249 cout << "failure writing file memstat.d" << endl;
252 fprintf(ff, "%12s %12s %12s %12s %12s\n",
253 "BlockSize", "NbAllocated", "NbLeft", "Allocated", "Left");
254 for (itLst.Init(aColl); itLst.More(); itLst.Next())
256 const StorageInfo& aInfo = itLst.Value();
257 Standard_Integer nbLeft = aInfo.nbAlloc - aInfo.nbFree;
258 Standard_Size aSizeAlloc = aInfo.nbAlloc * aInfo.roundSize;
259 Standard_Size aSizeLeft = nbLeft * aInfo.roundSize;
260 fprintf(ff, "%12d %12d %12d %12d %12d\n", aInfo.roundSize,
261 aInfo.nbAlloc, nbLeft, aSizeAlloc, aSizeLeft);
262 aTotAlloc += aSizeAlloc;
263 aTotLeft += aSizeLeft;
265 fprintf(ff, "%12s %12s %12s %12d %12d\n", "Total:", "", "",
266 aTotAlloc, aTotLeft);
268 if (!StorageIDSet().IsEmpty())
270 fprintf(ff, "Alive allocation numbers of size=%d\n", StandardCallBack_CatchSize());
271 NCollection_Map<Standard_Size>::Iterator itMap1(StorageIDSet());
272 for (; itMap1.More(); itMap1.Next())
273 fprintf(ff, "%d\n", itMap1.Key());