Updated copyright
[libcds.git] / cds / memory / michael / procheap_stat.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #ifndef CDSLIB_MEMORY_MICHAEL_ALLOCATOR_PROCHEAP_STAT_H
32 #define CDSLIB_MEMORY_MICHAEL_ALLOCATOR_PROCHEAP_STAT_H
33
34 #include <cds/algo/atomic.h>
35
36 namespace cds { namespace memory { namespace michael {
37
38         /// processor heap statistics
39     /**
40         This class is implementation of \ref opt::procheap_stat option.
41         The statistic counter implementation is based on atomic operations.
42
43         Template parameters:
44             - \p INC_FENCE - memory fence for increment operation (default is release semantics)
45             - \p READ_FENCE - memory fence for reading of statistic values (default is acquire semantics)
46     */
47     class procheap_atomic_stat
48     {
49         //@cond
50         atomics::atomic<size_t>      nAllocFromActive    ;  ///< Event count of allocation from active superblock
51         atomics::atomic<size_t>      nAllocFromPartial   ;  ///< Event count of allocation from partial superblock
52         atomics::atomic<size_t>      nAllocFromNew       ;  ///< Event count of allocation from new superblock
53         atomics::atomic<size_t>      nFreeCount          ;  ///< \ref free function call count
54         atomics::atomic<size_t>      nBlockCount         ;  ///< Count of superblock allocated
55         atomics::atomic<size_t>      nBlockDeallocCount  ;  ///< Count of superblock deallocated
56         atomics::atomic<size_t>      nDescAllocCount     ;  ///< Count of superblock descriptors
57         atomics::atomic<size_t>      nDescFull           ;  ///< Count of full superblock
58         atomics::atomic<unsigned long long> nBytesAllocated     ;  ///< Count of allocated bytes
59         atomics::atomic<unsigned long long> nBytesDeallocated   ;  ///< Count of deallocated bytes
60
61         atomics::atomic<size_t>      nActiveDescCASFailureCount ;   ///< CAS failure counter for active block of \p alloc_from_active Heap function
62         atomics::atomic<size_t>      nActiveAnchorCASFailureCount;   ///< CAS failure counter for active block of \p alloc_from_active Heap function
63         atomics::atomic<size_t>      nPartialDescCASFailureCount ;   ///< CAS failure counter for partial block of \p alloc_from_partial Heap function
64         atomics::atomic<size_t>      nPartialAnchorCASFailureCount;   ///< CAS failure counter for partial block of \p alloc_from_partial Heap function
65
66         //@endcond
67
68     public:
69         //@cond
70         procheap_atomic_stat()
71             : nAllocFromActive(0)
72             , nAllocFromPartial(0)
73             , nAllocFromNew(0)
74             , nFreeCount(0)
75             , nBlockCount(0)
76             , nDescFull(0)
77             , nBytesAllocated(0)
78             , nBytesDeallocated(0)
79             , nActiveDescCASFailureCount(0)
80             , nActiveAnchorCASFailureCount(0)
81             , nPartialDescCASFailureCount(0)
82             , nPartialAnchorCASFailureCount(0)
83         {}
84         //@endcond
85
86     public:
87         /// Increment event counter of allocation from active superblock
88         void incAllocFromActive()
89         {
90             nAllocFromActive.fetch_add( 1, atomics::memory_order_relaxed );
91         }
92         /// Increment event counter of allocation from active superblock by \p n
93         void incAllocFromActive( size_t n )
94         {
95             nAllocFromActive.fetch_add( n, atomics::memory_order_relaxed );
96         }
97
98         /// Increment event counter of allocation from partial superblock
99         void incAllocFromPartial()
100         {
101             nAllocFromPartial.fetch_add( 1, atomics::memory_order_relaxed );
102         }
103         /// Increment event counter of allocation from partial superblock by \p n
104         void incAllocFromPartial( size_t n )
105         {
106             nAllocFromPartial.fetch_add( n, atomics::memory_order_relaxed );
107         }
108
109         /// Increment event count of allocation from new superblock
110         void incAllocFromNew()
111         {
112             nAllocFromNew.fetch_add( 1, atomics::memory_order_relaxed );
113         }
114         /// Increment event count of allocation from new superblock by \p n
115         void incAllocFromNew( size_t n )
116         {
117             nAllocFromNew.fetch_add( n, atomics::memory_order_relaxed );
118         }
119
120         /// Increment event counter of free calling
121         void incFreeCount()
122         {
123             nFreeCount.fetch_add( 1, atomics::memory_order_relaxed );
124         }
125         /// Increment event counter of free calling by \p n
126         void incFreeCount( size_t n )
127         {
128             nFreeCount.fetch_add( n, atomics::memory_order_relaxed );
129         }
130
131         /// Increment counter of superblock allocated
132         void incBlockAllocated()
133         {
134             nBlockCount.fetch_add( 1, atomics::memory_order_relaxed );
135         }
136         /// Increment counter of superblock allocated by \p n
137         void incBlockAllocated( size_t n )
138         {
139             nBlockCount.fetch_add( n, atomics::memory_order_relaxed );
140         }
141
142         /// Increment counter of superblock deallocated
143         void incBlockDeallocated()
144         {
145             nBlockDeallocCount.fetch_add( 1, atomics::memory_order_relaxed );
146         }
147         /// Increment counter of superblock deallocated by \p n
148         void incBlockDeallocated( size_t n )
149         {
150             nBlockDeallocCount.fetch_add( n, atomics::memory_order_relaxed );
151         }
152
153         /// Increment counter of superblock descriptor allocated
154         void incDescAllocCount()
155         {
156             nDescAllocCount.fetch_add( 1, atomics::memory_order_relaxed );
157         }
158         /// Increment counter of superblock descriptor allocated by \p n
159         void incDescAllocCount( size_t n )
160         {
161             nDescAllocCount.fetch_add( n, atomics::memory_order_relaxed );
162         }
163
164         /// Increment counter of full superblock descriptor
165         void incDescFull()
166         {
167             nDescFull.fetch_add( 1, atomics::memory_order_relaxed );
168         }
169         /// Increment counter of full superblock descriptor by \p n
170         void incDescFull( size_t n )
171         {
172             nDescFull.fetch_add( n, atomics::memory_order_relaxed );
173         }
174
175         /// Decrement counter of full superblock descriptor
176         void decDescFull()
177         {
178             nDescFull.fetch_sub( 1, atomics::memory_order_relaxed );
179         }
180         /// Decrement counter of full superblock descriptor by \p n
181         void decDescFull(size_t n)
182         {
183             nDescFull.fetch_sub( n, atomics::memory_order_relaxed );
184         }
185         /// Add \p nBytes to allocated bytes counter
186         void incAllocatedBytes( size_t nBytes )
187         {
188             nBytesAllocated.fetch_add( nBytes, atomics::memory_order_relaxed );
189         }
190         /// Add \p nBytes to deallocated bytes counter
191         void incDeallocatedBytes( size_t nBytes )
192         {
193             nBytesDeallocated.fetch_add( nBytes, atomics::memory_order_relaxed);
194         }
195
196         /// Add \p nCount to CAS failure counter of updating \p active field of active descriptor for \p alloc_from_active internal Heap function
197         void incActiveDescCASFailureCount( int nCount )
198         {
199             nActiveDescCASFailureCount.fetch_add( nCount, atomics::memory_order_relaxed );
200         }
201
202         /// Add \p nCount to CAS failure counter of updating \p anchor field of active descriptor for \p alloc_from_active internal Heap function
203         void incActiveAnchorCASFailureCount( int nCount )
204         {
205             nActiveAnchorCASFailureCount.fetch_add( nCount, atomics::memory_order_relaxed );
206         }
207
208         /// Add \p nCount to CAS failure counter of updating \p active field of partial descriptor for \p alloc_from_partial internal Heap function
209         void incPartialDescCASFailureCount( int nCount )
210         {
211             nPartialDescCASFailureCount.fetch_add( nCount, atomics::memory_order_relaxed );
212         }
213
214         /// Add \p nCount to CAS failure counter of updating \p anchor field of partial descriptor for \p alloc_from_partial internal Heap function
215         void incPartialAnchorCASFailureCount( int nCount )
216         {
217             nPartialAnchorCASFailureCount.fetch_add( nCount, atomics::memory_order_relaxed );
218         }
219
220         // -----------------------------------------------------------------
221         // Reading
222
223         /// Read event counter of allocation from active superblock
224         size_t allocFromActive() const
225         {
226             return nAllocFromActive.load(atomics::memory_order_relaxed);
227         }
228
229         /// Read event counter of allocation from partial superblock
230         size_t allocFromPartial() const
231         {
232             return nAllocFromPartial.load(atomics::memory_order_relaxed);
233         }
234
235         /// Read event count of allocation from new superblock
236         size_t allocFromNew() const
237         {
238             return nAllocFromNew.load(atomics::memory_order_relaxed);
239         }
240
241         /// Read event counter of free calling
242         size_t freeCount() const
243         {
244             return nFreeCount.load(atomics::memory_order_relaxed);
245         }
246
247         /// Read counter of superblock allocated
248         size_t blockAllocated() const
249         {
250             return nBlockCount.load(atomics::memory_order_relaxed);
251         }
252
253         /// Read counter of superblock deallocated
254         size_t blockDeallocated() const
255         {
256             return nBlockDeallocCount.load(atomics::memory_order_relaxed);
257         }
258
259         /// Read counter of superblock descriptor allocated
260         size_t descAllocCount() const
261         {
262             return nDescAllocCount.load(atomics::memory_order_relaxed);
263         }
264
265         /// Read counter of full superblock descriptor
266         size_t descFull() const
267         {
268             return nDescFull.load(atomics::memory_order_relaxed);
269         }
270
271         /// Get counter of allocated bytes
272         /**
273             This counter only counts the bytes allocated by Heap, OS allocation (large blocks) is not counted.
274
275             To get count of bytes allocated but not yet deallocated you should call
276             \code allocatedBytes() - deallocatedBytes() \endcode
277         */
278         uint64_t allocatedBytes() const
279         {
280             return nBytesAllocated.load(atomics::memory_order_relaxed);
281         }
282
283         /// Get counter of deallocated bytes
284         /**
285             This counter only counts the bytes allocated by Heap, OS allocation (large blocks) is not counted.unter of deallocated bytes
286
287             See \ref allocatedBytes notes
288         */
289         uint64_t deallocatedBytes() const
290         {
291             return nBytesDeallocated.load(atomics::memory_order_relaxed);
292         }
293
294         /// Get CAS failure counter of updating \p active field of active descriptor for \p alloc_from_active internal Heap function
295         size_t activeDescCASFailureCount() const
296         {
297             return nActiveDescCASFailureCount.load(atomics::memory_order_relaxed);
298         }
299
300         /// Get CAS failure counter of updating \p anchor field of active descriptor for \p alloc_from_active internal Heap function
301         size_t activeAnchorCASFailureCount() const
302         {
303             return nActiveAnchorCASFailureCount.load(atomics::memory_order_relaxed);
304         }
305
306         /// Get CAS failure counter of updating \p active field of partial descriptor for \p alloc_from_active internal Heap function
307         size_t partialDescCASFailureCount() const
308         {
309             return nPartialDescCASFailureCount.load(atomics::memory_order_relaxed);
310         }
311
312         /// Get CAS failure counter of updating \p anchor field of partial descriptor for \p alloc_from_active internal Heap function
313         size_t partialAnchorCASFailureCount() const
314         {
315             return nPartialAnchorCASFailureCount.load(atomics::memory_order_relaxed);
316         }
317     };
318
319     /// Empty processor heap statistics
320     /**
321         This class is dummy implementation of \ref opt::procheap_stat option.
322         No statistic gathering is performed.
323
324         Interface - see procheap_atomic_stat.
325         All getter methods return 0.
326     */
327     class procheap_empty_stat
328     {
329     //@cond
330     public:
331         void incAllocFromActive()
332         {}
333         void incAllocFromPartial()
334         {}
335         void incAllocFromNew()
336         {}
337         void incFreeCount()
338         {}
339         void incBlockAllocated()
340         {}
341         void incBlockDeallocated()
342         {}
343         void incDescAllocCount()
344         {}
345         void incDescFull()
346         {}
347         void decDescFull()
348         {}
349
350         // Add -------------------------------------------------------------
351         void incAllocFromActive(size_t)
352         {}
353         void incAllocFromPartial(size_t)
354         {}
355         void incAllocFromNew(size_t)
356         {}
357         void incFreeCount(size_t)
358         {}
359         void incBlockAllocated(size_t)
360         {}
361         void incBlockDeallocated(size_t)
362         {}
363         void incDescAllocCount(size_t)
364         {}
365         void incDescFull(size_t)
366         {}
367         void decDescFull(size_t)
368         {}
369         void incAllocatedBytes( size_t /*nBytes*/ )
370         {}
371         void incDeallocatedBytes( size_t /*nBytes*/ )
372         {}
373         void incActiveDescCASFailureCount( int /*nCount*/ )
374         {}
375         void incActiveAnchorCASFailureCount( int /*nCount*/ )
376         {}
377         void incPartialDescCASFailureCount( int /*nCount*/ )
378         {}
379         void incPartialAnchorCASFailureCount( int /*nCount*/ )
380         {}
381
382         // -----------------------------------------------------------------
383         // Reading
384
385         size_t allocFromActive() const
386         { return 0; }
387         size_t allocFromPartial() const
388         { return 0; }
389         size_t allocFromNew() const
390         { return 0; }
391         size_t freeCount() const
392         { return 0; }
393         size_t blockAllocated() const
394         { return 0; }
395         size_t blockDeallocated() const
396         { return 0; }
397         size_t descAllocCount() const
398         { return 0; }
399         size_t descFull() const
400         { return 0; }
401         uint64_t allocatedBytes() const
402         { return 0; }
403         uint64_t deallocatedBytes() const
404         { return 0; }
405         size_t activeDescCASFailureCount() const
406         { return 0; }
407         size_t activeAnchorCASFailureCount() const
408         { return 0; }
409         size_t partialDescCASFailureCount() const
410         { return 0; }
411         size_t partialAnchorCASFailureCount() const
412         { return 0; }
413
414     //@endcond
415     };
416
417
418 }}} // namespace cds::memory::michael
419
420 #endif  /// CDSLIB_MEMORY_MICHAEL_ALLOCATOR_PROCHEAP_STAT_H