]>
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; | |
112 | private: | |
113 | const char *label; | |
114 | }; | |
115 | ||
116 | /* Support late binding of pool type for allocator agnostic classes */ | |
117 | class MemAllocatorProxy | |
83d8f9f4 | 118 | { |
b001e822 | 119 | public: |
120 | inline MemAllocatorProxy(char const *aLabel, size_t const &); | |
121 | void *alloc(); | |
122 | void free(void *); | |
123 | int inUseCount() const; | |
124 | size_t objectSize() const; | |
125 | MemPoolMeter const &getMeter() const; | |
126 | int getStats(MemPoolStats * stats); | |
127 | char const * objectType() const; | |
128 | private: | |
129 | MemAllocator *getAllocator() const; | |
d96ceb8e | 130 | const char *label; |
b001e822 | 131 | size_t size; |
132 | mutable MemAllocator *theAllocator; | |
133 | }; | |
134 | /* help for classes */ | |
135 | /* Put this in the class */ | |
136 | #define MEMPROXY_CLASS(CLASS) \ | |
137 | /* TODO change syntax to allow moving into .cci files */ \ | |
138 | inline void *operator new(size_t); \ | |
139 | inline void operator delete(void *); \ | |
140 | static inline MemAllocatorProxy &Pool() | |
141 | ||
142 | /* put this in the class .h, or .cci as appropriate */ | |
143 | #define MEMPROXY_CLASS_INLINE(CLASS) \ | |
144 | MemAllocatorProxy& CLASS::Pool() \ | |
145 | { \ | |
146 | static MemAllocatorProxy thePool(#CLASS, sizeof (CLASS)); \ | |
147 | return thePool; \ | |
148 | } \ | |
149 | \ | |
150 | void * \ | |
151 | CLASS::operator new (size_t byteCount) \ | |
152 | { \ | |
153 | /* derived classes with different sizes must implement their own new */ \ | |
154 | assert (byteCount == sizeof (CLASS)); \ | |
155 | \ | |
156 | return Pool().alloc(); \ | |
157 | } \ | |
158 | \ | |
159 | void \ | |
160 | CLASS::operator delete (void *address) \ | |
161 | { \ | |
162 | Pool().free(address); \ | |
163 | } | |
164 | ||
165 | class MemImplementingAllocator : public MemAllocator | |
166 | { | |
167 | public: | |
168 | MemImplementingAllocator(char const *aLabel, size_t aSize); | |
169 | virtual MemPoolMeter const &getMeter() const; | |
170 | virtual MemPoolMeter &getMeter(); | |
171 | virtual void flushMetersFull(); | |
172 | virtual void flushMeters(); | |
173 | virtual void *alloc(); | |
174 | virtual void free(void *); | |
175 | virtual bool idleTrigger(int shift) const = 0; | |
176 | virtual void clean(time_t maxage) = 0; | |
177 | /* Hint to the allocator - may be ignored */ | |
178 | virtual void setChunkSize(size_t chunksize) {} | |
179 | virtual size_t objectSize() const; | |
180 | protected: | |
181 | virtual void *allocate() = 0; | |
182 | virtual void deallocate(void *) = 0; | |
183 | private: | |
184 | MemPoolMeter meter; | |
185 | public: | |
186 | MemImplementingAllocator *next; | |
187 | public: | |
188 | size_t alloc_calls; | |
189 | size_t free_calls; | |
d96ceb8e | 190 | size_t obj_size; |
b001e822 | 191 | }; |
192 | ||
193 | class MemPool : public MemImplementingAllocator | |
194 | { | |
195 | public: | |
196 | friend class MemChunk; | |
197 | MemPool(const char *label, size_t obj_size); | |
198 | ~MemPool(); | |
199 | void convertFreeCacheToChunkFreeCache(); | |
200 | virtual void clean(time_t maxage); | |
201 | virtual int getStats(MemPoolStats * stats); | |
202 | void createChunk(); | |
203 | void *get(); | |
204 | void push(void *obj); | |
205 | protected: | |
206 | virtual void *allocate(); | |
207 | virtual void deallocate(void *); | |
208 | public: | |
209 | virtual void setChunkSize(size_t chunksize); | |
210 | virtual bool idleTrigger(int shift) const; | |
211 | ||
d96ceb8e | 212 | size_t chunk_size; |
213 | int chunk_capacity; | |
214 | int memPID; | |
215 | int chunkCount; | |
d96ceb8e | 216 | size_t inuse; |
217 | size_t idle; | |
218 | void *freeCache; | |
219 | MemChunk *nextFreeChunk; | |
220 | MemChunk *Chunks; | |
b001e822 | 221 | Splay<MemChunk *> allChunks; |
222 | }; | |
223 | ||
224 | class MemMalloc : public MemImplementingAllocator | |
225 | { | |
226 | public: | |
227 | MemMalloc(char const *label, size_t aSize); | |
228 | virtual bool idleTrigger(int shift) const; | |
229 | virtual void clean(time_t maxage); | |
230 | virtual int getStats(MemPoolStats * stats); | |
231 | protected: | |
232 | virtual void *allocate(); | |
233 | virtual void deallocate(void *); | |
d96ceb8e | 234 | }; |
235 | ||
b001e822 | 236 | class MemChunk |
83d8f9f4 | 237 | { |
b001e822 | 238 | public: |
239 | MemChunk(MemPool *pool); | |
240 | ~MemChunk(); | |
d96ceb8e | 241 | void *freeList; |
242 | void *objCache; | |
243 | int inuse_count; | |
244 | MemChunk *nextFreeChunk; | |
245 | MemChunk *next; | |
246 | time_t lastref; | |
b001e822 | 247 | MemPool *pool; |
d96ceb8e | 248 | }; |
249 | ||
b001e822 | 250 | class MemPoolStats |
83d8f9f4 | 251 | { |
b001e822 | 252 | public: |
253 | MemAllocator *pool; | |
d96ceb8e | 254 | const char *label; |
255 | MemPoolMeter *meter; | |
256 | int obj_size; | |
257 | int chunk_capacity; | |
258 | int chunk_size; | |
259 | ||
260 | int chunks_alloc; | |
261 | int chunks_inuse; | |
262 | int chunks_partial; | |
263 | int chunks_free; | |
264 | ||
265 | int items_alloc; | |
266 | int items_inuse; | |
267 | int items_idle; | |
268 | ||
269 | int overhead; | |
270 | }; | |
271 | ||
83d8f9f4 | 272 | struct _MemPoolGlobalStats |
273 | { | |
d96ceb8e | 274 | MemPoolMeter *TheMeter; |
275 | ||
276 | int tot_pools_alloc; | |
277 | int tot_pools_inuse; | |
278 | int tot_pools_mempid; | |
279 | ||
280 | int tot_chunks_alloc; | |
281 | int tot_chunks_inuse; | |
282 | int tot_chunks_partial; | |
283 | int tot_chunks_free; | |
284 | ||
285 | int tot_items_alloc; | |
286 | int tot_items_inuse; | |
287 | int tot_items_idle; | |
288 | ||
289 | int tot_overhead; | |
290 | int mem_idle_limit; | |
291 | }; | |
292 | ||
293 | #define SIZEOF_CHUNK ( ( sizeof(MemChunk) + sizeof(double) -1) / sizeof(double) ) * sizeof(double); | |
294 | ||
d96ceb8e | 295 | /* Allocator API */ |
b001e822 | 296 | extern MemPoolIterator * memPoolIterate(void); |
297 | extern MemImplementingAllocator * memPoolIterateNext(MemPoolIterator * iter); | |
298 | extern void memPoolIterateDone(MemPoolIterator ** iter); | |
d96ceb8e | 299 | |
b001e822 | 300 | /* Stats API - not sured how to refactor yet */ |
301 | extern int memPoolGetGlobalStats(MemPoolGlobalStats * stats); | |
d96ceb8e | 302 | |
b001e822 | 303 | extern int memPoolInUseCount(MemAllocator *); |
304 | extern int memPoolsTotalAllocated(void); | |
d96ceb8e | 305 | |
b001e822 | 306 | MemAllocatorProxy::MemAllocatorProxy(char const *aLabel, size_t const &aSize) : label (aLabel), size(aSize), theAllocator (NULL) |
307 | { | |
308 | } | |
d96ceb8e | 309 | |
d96ceb8e | 310 | |
311 | #endif /* _MEM_POOLS_H_ */ |