CookMem 1.4.0
A C++ memory context / allocator
Loading...
Searching...
No Matches
logger.h
1/*
2 * Copyright (c) 2021-2026 Heng Yuan
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef COOK_MEM_LOGGER_H
17#define COOK_MEM_LOGGER_H
18
19#include <cstddef>
20#include <cstdio>
21
22#include "exception.h"
23
24namespace cookmem
25{
26
51
59{
60public:
61 virtual ~MemLogger () { }
62
71 virtual void
72 logGetSegment (void* segment, std::size_t segmentSize) = 0;
73
82 virtual void
83 logFreeSegment (void* segment, std::size_t segmentSize) = 0;
84
86 virtual void
88
99 virtual void
101
113 virtual void
114 logReallocation (void* userPtr, std::size_t oldUserSize, std::size_t newUserSize) = 0;
115
124 virtual void
125 logDeallocation (void* userPtr, std::size_t userSize) = 0;
126
139 virtual void
140 logError (void* userPtr, MemError_et error, const char* file = __FILE__, int line = __LINE__) = 0;
141};
142
151{
152public:
155 {
156 }
157
159 inline void logGetSegment (void*, std::size_t) { }
160
162 inline void logFreeSegment (void*, std::size_t) { }
163
165 inline void logTrimEmptySegments () { }
166
168 inline void logAllocation (void*, std::size_t, MemAllocType_et) { }
169
171 inline void logReallocation (void*, std::size_t, std::size_t) { }
172
174 inline void logDeallocation (void*, std::size_t) { }
175
188 inline void
189 logError (void*,
191 const char* file = __FILE__,
192 int line = __LINE__)
193 {
194 throw Exception (error, "memory corruption detected.", file, line);
195 }
196};
197
202{
203public:
205 : m_numAllocations (0),
206 m_numDeallocations (0),
207 m_numGetSegments (0),
208 m_numFreeSegments (0),
209 m_numTrimEmptySegments (0),
210 m_totalAllocated (0),
211 m_totalDeallocated (0),
212 m_totalGetSegmentSize (0),
213 m_totalFreeSegmentSize (0),
214 m_currentAllocated (0),
215 m_peakAllocated (0),
216 m_currentSegments (0),
217 m_peakSegments (0),
218 m_currentSegmentSize (0),
219 m_peakSegmentSize (0),
220 m_numAllocationsByType {}
221 {
222 }
223
225 std::size_t getNumAllocations () const { return m_numAllocations; }
228 {
229 return m_numAllocationsByType[allocType];
230 }
232 std::size_t getNumDeallocations () const { return m_numDeallocations; }
234 std::size_t getNumGetSegments () const { return m_numGetSegments; }
236 std::size_t getNumFreeSegments () const { return m_numFreeSegments; }
238 std::size_t getNumTrimEmptySegments () const { return m_numTrimEmptySegments; }
240 std::size_t getTotalAllocated () const { return m_totalAllocated; }
242 std::size_t getTotalDeallocated () const { return m_totalDeallocated; }
244 std::size_t getTotalGetSegmentSize () const { return m_totalGetSegmentSize; }
246 std::size_t getTotalFreeSegmentSize () const { return m_totalFreeSegmentSize; }
248 std::size_t getCurrentAllocated () const { return m_currentAllocated; }
250 std::size_t getPeakAllocated () const { return m_peakAllocated; }
252 std::size_t getCurrentSegments () const { return m_currentSegments; }
254 std::size_t getPeakSegments () const { return m_peakSegments; }
256 std::size_t getCurrentSegmentSize () const { return m_currentSegmentSize; }
258 std::size_t getPeakSegmentSize () const { return m_peakSegmentSize; }
259
261 // Internal use only. These setters are used by StatsLogger.
262 void setNumAllocations (std::size_t value) { m_numAllocations = value; }
263 void setNumAllocations (MemAllocType_et allocType, std::size_t value)
264 {
265 m_numAllocationsByType[allocType] = value;
266 }
267 void setNumDeallocations (std::size_t value) { m_numDeallocations = value; }
268 void setNumGetSegments (std::size_t value) { m_numGetSegments = value; }
269 void setNumFreeSegments (std::size_t value) { m_numFreeSegments = value; }
270 void setNumTrimEmptySegments (std::size_t value) { m_numTrimEmptySegments = value; }
271 void setTotalAllocated (std::size_t value) { m_totalAllocated = value; }
272 void setTotalDeallocated (std::size_t value) { m_totalDeallocated = value; }
273 void setTotalGetSegmentSize (std::size_t value) { m_totalGetSegmentSize = value; }
274 void setTotalFreeSegmentSize (std::size_t value) { m_totalFreeSegmentSize = value; }
275 void setCurrentAllocated (std::size_t value) { m_currentAllocated = value; }
276 void setPeakAllocated (std::size_t value) { m_peakAllocated = value; }
277 void setCurrentSegments (std::size_t value) { m_currentSegments = value; }
278 void setPeakSegments (std::size_t value) { m_peakSegments = value; }
279 void setCurrentSegmentSize (std::size_t value) { m_currentSegmentSize = value; }
280 void setPeakSegmentSize (std::size_t value) { m_peakSegmentSize = value; }
282
286 void
287 printStats () const
288 {
289 std::printf ("current allocations: %zu bytes, peak allocations: %zu bytes, "
290 "current segments: %zu (%zu bytes), peak segments: %zu (%zu bytes)\n",
291 m_currentAllocated,
292 m_peakAllocated,
293 m_currentSegments,
294 m_currentSegmentSize,
295 m_peakSegments,
296 m_peakSegmentSize);
297 std::printf ("empty-segment trimming passes: %zu\n", m_numTrimEmptySegments);
298
299 std::printf ("allocations by type:\n");
300 for (std::size_t i = 0; i < MEM_ALLOC_COUNT; ++i)
301 {
302 std::printf (" %s: %zu\n",
303 getAllocationTypeName (static_cast<MemAllocType_et> (i)),
304 m_numAllocationsByType[i]);
305 }
306 }
307
315 static const char*
317 {
318 static const char* const names[MEM_ALLOC_COUNT] =
319 {
320 "none",
321 "small",
322 "tree",
323 "dv",
324 "arena",
325 "big"
326 };
327 std::size_t index = static_cast<std::size_t> (allocType);
328 return index < MEM_ALLOC_COUNT ? names[index] : "unknown";
329 }
330
331private:
332 std::size_t m_numAllocations;
333 std::size_t m_numDeallocations;
334 std::size_t m_numGetSegments;
335 std::size_t m_numFreeSegments;
336 std::size_t m_numTrimEmptySegments;
337 std::size_t m_totalAllocated;
338 std::size_t m_totalDeallocated;
339 std::size_t m_totalGetSegmentSize;
340 std::size_t m_totalFreeSegmentSize;
341 std::size_t m_currentAllocated;
342 std::size_t m_peakAllocated;
343 std::size_t m_currentSegments;
344 std::size_t m_peakSegments;
345 std::size_t m_currentSegmentSize;
346 std::size_t m_peakSegmentSize;
347 std::size_t m_numAllocationsByType[MEM_ALLOC_COUNT];
348};
349
358{
359public:
361 void
363 {
364 m_stats.setNumTrimEmptySegments (m_stats.getNumTrimEmptySegments () + 1);
365 }
366
368 void
369 logGetSegment (void* segment, std::size_t segmentSize)
370 {
371 if (segment == nullptr)
372 {
373 return;
374 }
375 m_stats.setNumGetSegments (m_stats.getNumGetSegments () + 1);
376 m_stats.setTotalGetSegmentSize (m_stats.getTotalGetSegmentSize () + segmentSize);
377
378 std::size_t numSegments = m_stats.getCurrentSegments () + 1;
379 std::size_t segmentSizeTotal = m_stats.getCurrentSegmentSize () + segmentSize;
380 m_stats.setCurrentSegments (numSegments);
381 m_stats.setCurrentSegmentSize (segmentSizeTotal);
382 if (m_stats.getPeakSegments () < numSegments)
383 {
384 m_stats.setPeakSegments (numSegments);
385 }
386 if (m_stats.getPeakSegmentSize () < segmentSizeTotal)
387 {
388 m_stats.setPeakSegmentSize (segmentSizeTotal);
389 }
390 }
391
393 void
394 logFreeSegment (void* segment, std::size_t segmentSize)
395 {
396 if (segment == nullptr)
397 {
398 return;
399 }
400 m_stats.setNumFreeSegments (m_stats.getNumFreeSegments () + 1);
401 m_stats.setTotalFreeSegmentSize (m_stats.getTotalFreeSegmentSize () + segmentSize);
402 m_stats.setCurrentSegments (m_stats.getCurrentSegments () - 1);
403 m_stats.setCurrentSegmentSize (m_stats.getCurrentSegmentSize () - segmentSize);
404 }
405
407 void
409 {
410 if (userPtr != nullptr)
411 {
412 m_stats.setNumAllocations (m_stats.getNumAllocations () + 1);
413 m_stats.setTotalAllocated (m_stats.getTotalAllocated () + userSize);
414 std::size_t currentAllocated = m_stats.getCurrentAllocated () + userSize;
415 m_stats.setCurrentAllocated (currentAllocated);
416 if (m_stats.getPeakAllocated () < currentAllocated)
417 {
418 m_stats.setPeakAllocated (currentAllocated);
419 }
420 m_stats.setNumAllocations (allocType,
421 m_stats.getNumAllocations (allocType) + 1);
422 }
423 }
424
426 void
427 logReallocation (void* userPtr, std::size_t oldUserSize, std::size_t newUserSize)
428 {
429 if (userPtr != nullptr && newUserSize > oldUserSize)
430 {
431 std::size_t delta = newUserSize - oldUserSize;
432 m_stats.setTotalAllocated (m_stats.getTotalAllocated () + delta);
433 std::size_t currentAllocated = m_stats.getCurrentAllocated () + delta;
434 m_stats.setCurrentAllocated (currentAllocated);
435 if (m_stats.getPeakAllocated () < currentAllocated)
436 {
437 m_stats.setPeakAllocated (currentAllocated);
438 }
439 }
440 else if (userPtr != nullptr)
441 {
442 std::size_t delta = oldUserSize - newUserSize;
443 m_stats.setTotalDeallocated (m_stats.getTotalDeallocated () + delta);
444 m_stats.setCurrentAllocated (m_stats.getCurrentAllocated () - delta);
445 }
446 }
447
449 void
450 logDeallocation (void* userPtr, std::size_t userSize)
451 {
452 if (userPtr != nullptr)
453 {
454 m_stats.setNumDeallocations (m_stats.getNumDeallocations () + 1);
455 m_stats.setTotalDeallocated (m_stats.getTotalDeallocated () + userSize);
456 m_stats.setCurrentAllocated (m_stats.getCurrentAllocated () - userSize);
457 }
458 }
459
461 void
462 logError (void*,
464 const char* file = __FILE__,
465 int line = __LINE__)
466 {
467 throw Exception (error, "memory corruption detected.", file, line);
468 }
469
475 MemStatistics& getStats () { return m_stats; }
476
482 const MemStatistics& getStats () const { return m_stats; }
483
484private:
485 MemStatistics m_stats;
486};
487
488} // namespace cookmem
489
490#endif // COOK_MEM_LOGGER_H
Definition exception.h:39
Definition allocator.h:39
Definition logger.h:59
virtual void logDeallocation(void *userPtr, std::size_t userSize)=0
virtual void logError(void *userPtr, MemError_et error, const char *file=__FILE__, int line=__LINE__)=0
virtual void logFreeSegment(void *segment, std::size_t segmentSize)=0
virtual void logAllocation(void *userPtr, std::size_t userSize, MemAllocType_et allocType)=0
virtual void logGetSegment(void *segment, std::size_t segmentSize)=0
virtual void logTrimEmptySegments()=0
virtual void logReallocation(void *userPtr, std::size_t oldUserSize, std::size_t newUserSize)=0
Definition logger.h:151
void logAllocation(void *, std::size_t, MemAllocType_et)
Definition logger.h:168
void logFreeSegment(void *, std::size_t)
Definition logger.h:162
NoActionMemLogger()
Definition logger.h:154
void logTrimEmptySegments()
Definition logger.h:165
void logReallocation(void *, std::size_t, std::size_t)
Definition logger.h:171
void logGetSegment(void *, std::size_t)
Definition logger.h:159
void logDeallocation(void *, std::size_t)
Definition logger.h:174
void logError(void *, MemError_et error, const char *file=__FILE__, int line=__LINE__)
Definition logger.h:189
Definition logger.h:358
void logGetSegment(void *segment, std::size_t segmentSize)
Definition logger.h:369
void logTrimEmptySegments()
Definition logger.h:362
void logError(void *, MemError_et error, const char *file=__FILE__, int line=__LINE__)
Definition logger.h:462
MemStatistics & getStats()
Definition logger.h:475
void logReallocation(void *userPtr, std::size_t oldUserSize, std::size_t newUserSize)
Definition logger.h:427
void logDeallocation(void *userPtr, std::size_t userSize)
Definition logger.h:450
void logFreeSegment(void *segment, std::size_t segmentSize)
Definition logger.h:394
const MemStatistics & getStats() const
Definition logger.h:482
void logAllocation(void *userPtr, std::size_t userSize, MemAllocType_et allocType)
Definition logger.h:408
Definition allocator.h:29
MemError_et
Definition exception.h:28
MemAllocType_et
Definition logger.h:31
@ MEM_ALLOC_COUNT
Definition logger.h:49
@ MEM_ALLOC_TREE
Definition logger.h:37
@ MEM_ALLOC_BIG
Definition logger.h:43
@ MEM_ALLOC_ARENA
Definition logger.h:41
@ MEM_ALLOC_DV
Definition logger.h:39
@ MEM_ALLOC_SMALL
Definition logger.h:35
@ MEM_ALLOC_NONE
Definition logger.h:33
Definition logger.h:202
std::size_t getNumGetSegments() const
Definition logger.h:234
std::size_t getTotalDeallocated() const
Definition logger.h:242
std::size_t getNumAllocations(MemAllocType_et allocType) const
Definition logger.h:227
std::size_t getCurrentSegmentSize() const
Definition logger.h:256
static const char * getAllocationTypeName(MemAllocType_et allocType)
Definition logger.h:316
std::size_t getPeakAllocated() const
Definition logger.h:250
std::size_t getTotalAllocated() const
Definition logger.h:240
std::size_t getTotalGetSegmentSize() const
Definition logger.h:244
std::size_t getCurrentAllocated() const
Definition logger.h:248
std::size_t getNumDeallocations() const
Definition logger.h:232
std::size_t getTotalFreeSegmentSize() const
Definition logger.h:246
std::size_t getNumFreeSegments() const
Definition logger.h:236
std::size_t getCurrentSegments() const
Definition logger.h:252
std::size_t getNumTrimEmptySegments() const
Definition logger.h:238
std::size_t getNumAllocations() const
Definition logger.h:225
std::size_t getPeakSegmentSize() const
Definition logger.h:258
void printStats() const
Definition logger.h:287
std::size_t getPeakSegments() const
Definition logger.h:254