]>
Commit | Line | Data |
---|---|---|
d96ceb8e | 1 | |
2 | #ifndef _MEM_POOLS_H_ | |
3 | #define _MEM_POOLS_H_ | |
4 | ||
5 | #include "config.h" | |
f323a09d | 6 | #include "assert.h" |
d96ceb8e | 7 | #include "util.h" |
83d8f9f4 | 8 | |
d96ceb8e | 9 | #include "memMeter.h" |
b001e822 | 10 | #include "splay.h" |
d96ceb8e | 11 | |
12 | #if HAVE_GNUMALLOC_H | |
13 | #include <gnumalloc.h> | |
482aa790 | 14 | #elif HAVE_MALLOC_H |
d96ceb8e | 15 | #include <malloc.h> |
16 | #endif | |
17 | ||
18 | #if HAVE_MEMORY_H | |
19 | #include <memory.h> | |
20 | #endif | |
21 | ||
22 | #if !M_MMAP_MAX | |
23 | #if USE_DLMALLOC | |
24 | #define M_MMAP_MAX -4 | |
25 | #endif | |
26 | #endif | |
27 | ||
d96ceb8e | 28 | #define MB ((size_t)1024*1024) |
29 | #define mem_unlimited_size 2 * 1024 * MB | |
30 | #define toMB(size) ( ((double) size) / MB ) | |
31 | #define toKB(size) ( (size + 1024 - 1) / 1024 ) | |
32 | ||
33 | #define MEM_PAGE_SIZE 4096 | |
34 | #define MEM_CHUNK_SIZE 4096 * 4 | |
35 | #define MEM_CHUNK_MAX_SIZE 256 * 1024 /* 2MB */ | |
36 | #define MEM_MIN_FREE 32 | |
37 | #define MEM_MAX_FREE 65535 /* ushort is max number of items per chunk */ | |
38 | ||
b001e822 | 39 | class MemImplementingAllocator; |
40 | class MemChunk; | |
41 | class MemPoolStats; | |
83d8f9f4 | 42 | |
d96ceb8e | 43 | typedef struct _MemPoolGlobalStats MemPoolGlobalStats; |
83d8f9f4 | 44 | |
b001e822 | 45 | class MemPoolIterator |
83d8f9f4 | 46 | { |
b001e822 | 47 | public: |
48 | MemImplementingAllocator *pool; | |
d96ceb8e | 49 | MemPoolIterator * next; |
50 | }; | |
51 | ||
52 | /* object to track per-pool cumulative counters */ | |
83d8f9f4 | 53 | |
b001e822 | 54 | class mgb_t |
83d8f9f4 | 55 | { |
b001e822 | 56 | public: |
57 | mgb_t() : count(0), bytes(0){} | |
d96ceb8e | 58 | double count; |
59 | double bytes; | |
b001e822 | 60 | }; |
d96ceb8e | 61 | |
62 | /* object to track per-pool memory usage (alloc = inuse+idle) */ | |
83d8f9f4 | 63 | |
b001e822 | 64 | class MemPoolMeter |
83d8f9f4 | 65 | { |
b001e822 | 66 | public: |
67 | void flush(); | |
d96ceb8e | 68 | MemMeter alloc; |
69 | MemMeter inuse; | |
70 | MemMeter idle; | |
71 | mgb_t gb_saved; /* account Allocations */ | |
72 | mgb_t gb_osaved; /* history Allocations */ | |
73 | mgb_t gb_freed; /* account Free calls */ | |
74 | }; | |
75 | ||
b001e822 | 76 | class MemImplementingAllocator; |
77 | ||
78 | class MemPools | |
79 | { | |
80 | public: | |
81 | static MemPools &GetInstance(); | |
82 | MemPools(); | |
83 | void init(); | |
84 | void flushMeters(); | |
85 | MemImplementingAllocator * create(const char *label, size_t obj_size); | |
86 | MemImplementingAllocator * create(const char *label, size_t obj_size, bool const chunked); | |
87 | void setIdleLimit(size_t new_idle_limit); | |
88 | size_t const idleLimit() const; | |
89 | void clean(time_t maxage); | |
90 | void setDefaultPoolChunking(bool const &); | |
91 | MemImplementingAllocator *pools; | |
92 | int mem_idle_limit; | |
93 | int poolCount; | |
94 | bool defaultIsChunked; | |
95 | private: | |
96 | static MemPools *Instance; | |
97 | }; | |
98 | ||
d96ceb8e | 99 | /* a pool is a [growing] space for objects of the same size */ |
83d8f9f4 | 100 | |
b001e822 | 101 | class MemAllocator |
102 | { | |
103 | public: | |
104 | MemAllocator (char const *aLabel); | |
105 | virtual ~MemAllocator() {} | |
106 | virtual int getStats(MemPoolStats * stats) = 0; | |
107 | virtual MemPoolMeter const &getMeter() const = 0; | |
108 | virtual void *alloc() = 0; | |
109 | virtual void free(void *) = 0; | |
110 | virtual char const *objectType() const; | |
111 | virtual size_t objectSize() const = 0; | |
a3efa961 | 112 | int inUseCount(); |
04eb0689 | 113 | virtual void setChunkSize(size_t chunksize) {} |
b001e822 | 114 | private: |
115 | const char *label; | |
116 | }; | |
117 | ||
118 | /* Support late binding of pool type for allocator agnostic classes */ | |
119 | class MemAllocatorProxy | |
83d8f9f4 | 120 | { |
b001e822 | 121 | public: |
122 | inline MemAllocatorProxy(char const *aLabel, size_t const &); | |
123 | void *alloc(); | |
124 | void free(void *); | |
125 | int inUseCount() const; | |
126 | size_t objectSize() const; | |
127 | MemPoolMeter const &getMeter() const; | |
128 | int getStats(MemPoolStats * stats); | |
129 | char const * objectType() const; | |
130 | private: | |
131 | MemAllocator *getAllocator() const; | |
d96ceb8e | 132 | const char *label; |
b001e822 | 133 | size_t size; |
134 | mutable MemAllocator *theAllocator; | |
135 | }; | |
136 | /* help for classes */ | |
137 | /* Put this in the class */ | |
138 | #define MEMPROXY_CLASS(CLASS) \ | |
139 | /* TODO change syntax to allow moving into .cci files */ \ | |
140 | inline void *operator new(size_t); \ | |
141 | inline void operator delete(void *); \ | |
142 | static inline MemAllocatorProxy &Pool() | |
143 | ||
144 | /* put this in the class .h, or .cci as appropriate */ | |
145 | #define MEMPROXY_CLASS_INLINE(CLASS) \ | |
146 | MemAllocatorProxy& CLASS::Pool() \ | |
147 | { \ | |
148 | static MemAllocatorProxy thePool(#CLASS, sizeof (CLASS)); \ | |
149 | return thePool; \ | |
150 | } \ | |
151 | \ | |
152 | void * \ | |
153 | CLASS::operator new (size_t byteCount) \ | |
154 | { \ | |
155 | /* derived classes with different sizes must implement their own new */ \ | |
156 | assert (byteCount == sizeof (CLASS)); \ | |
157 | \ | |
158 | return Pool().alloc(); \ | |
159 | } \ | |
160 | \ | |
161 | void \ | |
162 | CLASS::operator delete (void *address) \ | |
163 | { \ | |
164 | Pool().free(address); \ | |
165 | } | |
166 | ||
167 | class MemImplementingAllocator : public MemAllocator | |
168 | { | |
169 | public: | |
170 | MemImplementingAllocator(char const *aLabel, size_t aSize); | |
171 | virtual MemPoolMeter const &getMeter() const; | |
172 | virtual MemPoolMeter &getMeter(); | |
173 | virtual void flushMetersFull(); | |
174 | virtual void flushMeters(); | |
175 | virtual void *alloc(); | |
176 | virtual void free(void *); | |
177 | virtual bool idleTrigger(int shift) const = 0; | |
178 | virtual void clean(time_t maxage) = 0; | |
179 | /* Hint to the allocator - may be ignored */ | |
180 | virtual void setChunkSize(size_t chunksize) {} | |
181 | virtual size_t objectSize() const; | |
182 | protected: | |
183 | virtual void *allocate() = 0; | |
184 | virtual void deallocate(void *) = 0; | |
185 | private: | |
186 | MemPoolMeter meter; | |
187 | public: | |
188 | MemImplementingAllocator *next; | |
189 | public: | |
190 | size_t alloc_calls; | |
191 | size_t free_calls; | |
d96ceb8e | 192 | size_t obj_size; |
b001e822 | 193 | }; |
194 | ||
195 | class MemPool : public MemImplementingAllocator | |
196 | { | |
197 | public: | |
198 | friend class MemChunk; | |
199 | MemPool(const char *label, size_t obj_size); | |
200 | ~MemPool(); | |
201 | void convertFreeCacheToChunkFreeCache(); | |
202 | virtual void clean(time_t maxage); | |
203 | virtual int getStats(MemPoolStats * stats); | |
204 | void createChunk(); | |
205 | void *get(); | |
206 | void push(void *obj); | |
207 | protected: | |
208 | virtual void *allocate(); | |
209 | virtual void deallocate(void *); | |
210 | public: | |
211 | virtual void setChunkSize(size_t chunksize); | |
212 | virtual bool idleTrigger(int shift) const; | |
213 | ||
d96ceb8e | 214 | size_t chunk_size; |
215 | int chunk_capacity; | |
216 | int memPID; | |
217 | int chunkCount; | |
d96ceb8e | 218 | size_t inuse; |
219 | size_t idle; | |
220 | void *freeCache; | |
221 | MemChunk *nextFreeChunk; | |
222 | MemChunk *Chunks; | |
b001e822 | 223 | Splay<MemChunk *> allChunks; |
224 | }; | |
225 | ||
226 | class MemMalloc : public MemImplementingAllocator | |
227 | { | |
228 | public: | |
229 | MemMalloc(char const *label, size_t aSize); | |
230 | virtual bool idleTrigger(int shift) const; | |
231 | virtual void clean(time_t maxage); | |
232 | virtual int getStats(MemPoolStats * stats); | |
233 | protected: | |
234 | virtual void *allocate(); | |
235 | virtual void deallocate(void *); | |
d96ceb8e | 236 | }; |
237 | ||
b001e822 | 238 | class MemChunk |
83d8f9f4 | 239 | { |
b001e822 | 240 | public: |
241 | MemChunk(MemPool *pool); | |
242 | ~MemChunk(); | |
d96ceb8e | 243 | void *freeList; |
244 | void *objCache; | |
245 | int inuse_count; | |
246 | MemChunk *nextFreeChunk; | |
247 | MemChunk *next; | |
248 | time_t lastref; | |
b001e822 | 249 | MemPool *pool; |
d96ceb8e | 250 | }; |
251 | ||
b001e822 | 252 | class MemPoolStats |
83d8f9f4 | 253 | { |
b001e822 | 254 | public: |
255 | MemAllocator *pool; | |
d96ceb8e | 256 | const char *label; |
257 | MemPoolMeter *meter; | |
258 | int obj_size; | |
259 | int chunk_capacity; | |
260 | int chunk_size; | |
261 | ||
262 | int chunks_alloc; | |
263 | int chunks_inuse; | |
264 | int chunks_partial; | |
265 | int chunks_free; | |
266 | ||
267 | int items_alloc; | |
268 | int items_inuse; | |
269 | int items_idle; | |
270 | ||
271 | int overhead; | |
272 | }; | |
273 | ||
83d8f9f4 | 274 | struct _MemPoolGlobalStats |
275 | { | |
d96ceb8e | 276 | MemPoolMeter *TheMeter; |
277 | ||
278 | int tot_pools_alloc; | |
279 | int tot_pools_inuse; | |
280 | int tot_pools_mempid; | |
281 | ||
282 | int tot_chunks_alloc; | |
283 | int tot_chunks_inuse; | |
284 | int tot_chunks_partial; | |
285 | int tot_chunks_free; | |
286 | ||
287 | int tot_items_alloc; | |
288 | int tot_items_inuse; | |
289 | int tot_items_idle; | |
290 | ||
291 | int tot_overhead; | |
292 | int mem_idle_limit; | |
293 | }; | |
294 | ||
295 | #define SIZEOF_CHUNK ( ( sizeof(MemChunk) + sizeof(double) -1) / sizeof(double) ) * sizeof(double); | |
296 | ||
04eb0689 | 297 | #define memPoolCreate MemPools::GetInstance().create |
298 | ||
d96ceb8e | 299 | /* Allocator API */ |
b001e822 | 300 | extern MemPoolIterator * memPoolIterate(void); |
301 | extern MemImplementingAllocator * memPoolIterateNext(MemPoolIterator * iter); | |
302 | extern void memPoolIterateDone(MemPoolIterator ** iter); | |
d96ceb8e | 303 | |
b001e822 | 304 | /* Stats API - not sured how to refactor yet */ |
305 | extern int memPoolGetGlobalStats(MemPoolGlobalStats * stats); | |
d96ceb8e | 306 | |
b001e822 | 307 | extern int memPoolInUseCount(MemAllocator *); |
308 | extern int memPoolsTotalAllocated(void); | |
d96ceb8e | 309 | |
b001e822 | 310 | MemAllocatorProxy::MemAllocatorProxy(char const *aLabel, size_t const &aSize) : label (aLabel), size(aSize), theAllocator (NULL) |
311 | { | |
312 | } | |
d96ceb8e | 313 | |
d96ceb8e | 314 | |
315 | #endif /* _MEM_POOLS_H_ */ |