]>
Commit | Line | Data |
---|---|---|
acf5589a | 1 | |
2 | /* | |
d8b249ef | 3 | * $Id: mem.cc,v 1.19 1998/03/20 18:06:45 rousskov Exp $ |
acf5589a | 4 | * |
7021844c | 5 | * DEBUG: section 13 High Level Memory Pool Management |
acf5589a | 6 | * AUTHOR: Harvest Derived |
7 | * | |
8 | * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ | |
9 | * -------------------------------------------------------- | |
10 | * | |
11 | * Squid is the result of efforts by numerous individuals from the | |
12 | * Internet community. Development is led by Duane Wessels of the | |
13 | * National Laboratory for Applied Network Research and funded by | |
14 | * the National Science Foundation. | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with this program; if not, write to the Free Software | |
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
29 | * | |
30 | */ | |
31 | ||
32 | #include "squid.h" | |
33 | ||
7021844c | 34 | /* module globals */ |
acf5589a | 35 | |
7021844c | 36 | static MemPool *MemPools[MEM_MAX]; |
acf5589a | 37 | |
9fe7e747 | 38 | /* string pools */ |
39 | #define mem_str_pool_count 3 | |
40 | static const struct { | |
41 | const char *name; | |
42 | size_t obj_size; | |
43 | } StrPoolsAttrs[mem_str_pool_count] = { | |
44 | { "Short Strings", 36, }, /* to fit rfc1123 and similar */ | |
45 | { "Medium Strings", 128, }, /* to fit most urls */ | |
46 | { "Long Strings", 512 } /* other */ | |
47 | }; | |
48 | static struct { MemPool *pool; } StrPools[mem_str_pool_count]; | |
49 | static MemMeter StrCountMeter; | |
50 | static MemMeter StrVolumeMeter; | |
51 | ||
52 | ||
53 | /* local routines */ | |
54 | ||
4cc73db3 | 55 | /* |
56 | * we have a limit on _total_ amount of idle memory so we ignore | |
57 | * max_pages for now | |
58 | */ | |
acf5589a | 59 | static void |
7021844c | 60 | memDataInit(mem_type type, const char *name, size_t size, int max_pages_notused) |
acf5589a | 61 | { |
7021844c | 62 | assert(name && size); |
63 | MemPools[type] = memPoolCreate(name, size); | |
acf5589a | 64 | } |
65 | ||
9fe7e747 | 66 | static void |
67 | memStringStats(StoreEntry * sentry) | |
68 | { | |
69 | const char *pfmt = "%-20s\t %d\t %d\n"; | |
70 | int i; | |
71 | int pooled_count = 0; | |
72 | size_t pooled_volume = 0; | |
73 | /* heading */ | |
74 | storeAppendPrintf(sentry, | |
75 | "String Pool\t Impact\t\t\n" | |
76 | " \t (%%strings)\t (%%volume)\n"); | |
77 | /* table body */ | |
78 | for (i = 0; i < mem_str_pool_count; i++) { | |
79 | const MemPool *pool = StrPools[i].pool; | |
80 | const int plevel = pool->meter.inuse.level; | |
81 | storeAppendPrintf(sentry, pfmt, | |
82 | pool->label, | |
83 | xpercentInt(plevel, StrCountMeter.level), | |
84 | xpercentInt(plevel*pool->obj_size, StrVolumeMeter.level)); | |
85 | pooled_count += plevel; | |
86 | pooled_volume += plevel*pool->obj_size; | |
87 | } | |
88 | /* malloc strings */ | |
89 | storeAppendPrintf(sentry, pfmt, | |
90 | "Other Strings", | |
91 | xpercentInt(StrCountMeter.level-pooled_count, StrCountMeter.level), | |
92 | xpercentInt(StrVolumeMeter.level-pooled_volume, StrVolumeMeter.level)); | |
93 | } | |
94 | ||
acf5589a | 95 | static void |
7021844c | 96 | memStats(StoreEntry * sentry) |
acf5589a | 97 | { |
7021844c | 98 | storeBuffer(sentry); |
b4832aa9 | 99 | memReport(sentry); |
9fe7e747 | 100 | memStringStats(sentry); |
7021844c | 101 | storeBufferFlush(sentry); |
acf5589a | 102 | } |
103 | ||
7021844c | 104 | |
acf5589a | 105 | /* |
9fe7e747 | 106 | * public routines |
acf5589a | 107 | */ |
108 | ||
9fe7e747 | 109 | |
7021844c | 110 | /* find appropriate pool and use it (pools always init buffer with 0s) */ |
acf5589a | 111 | void * |
7021844c | 112 | memAllocate(mem_type type) |
acf5589a | 113 | { |
7021844c | 114 | return memPoolAlloc(MemPools[type]); |
acf5589a | 115 | } |
116 | ||
7021844c | 117 | /* find appropriate pool and use it */ |
acf5589a | 118 | void |
119 | memFree(mem_type type, void *p) | |
120 | { | |
7021844c | 121 | memPoolFree(MemPools[type], p); |
acf5589a | 122 | } |
123 | ||
9fe7e747 | 124 | /* allocate a variable size buffer using best-fit pool */ |
125 | void * | |
126 | memAllocBuf(size_t net_size, size_t *gross_size) | |
127 | { | |
128 | int i; | |
129 | MemPool *pool = NULL; | |
130 | assert(gross_size); | |
131 | for (i = 0; i < mem_str_pool_count; i++) { | |
132 | if (net_size <= StrPoolsAttrs[i].obj_size) { | |
133 | pool = StrPools[i].pool; | |
134 | break; | |
135 | } | |
136 | } | |
137 | *gross_size = pool ? pool->obj_size : net_size; | |
138 | assert(*gross_size >= net_size); | |
139 | memMeterInc(StrCountMeter); | |
140 | memMeterAdd(StrVolumeMeter, *gross_size); | |
141 | return pool ? memPoolAlloc(pool) : xcalloc(1, net_size); | |
142 | } | |
143 | ||
144 | /* free buffer allocated with memAllocBuf() */ | |
145 | void | |
146 | memFreeBuf(size_t size, void *buf) | |
147 | { | |
148 | int i; | |
149 | MemPool *pool = NULL; | |
150 | assert(size && buf); | |
151 | for (i = 0; i < mem_str_pool_count; i++) { | |
152 | if (size <= StrPoolsAttrs[i].obj_size) { | |
153 | assert(size == StrPoolsAttrs[i].obj_size); | |
154 | pool = StrPools[i].pool; | |
155 | break; | |
156 | } | |
157 | } | |
158 | memMeterDec(StrCountMeter); | |
159 | memMeterDel(StrVolumeMeter, size); | |
160 | pool ? memPoolFree(pool, buf) : xfree(buf); | |
161 | } | |
162 | ||
acf5589a | 163 | void |
164 | memInit(void) | |
165 | { | |
9fe7e747 | 166 | int i; |
acf5589a | 167 | mem_type t; |
7021844c | 168 | memInitModule(); |
169 | /* set all pointers to null */ | |
170 | memset(MemPools, '\0', sizeof(MemPools)); | |
171 | /* | |
172 | * it does not hurt much to have a lot of pools since sizeof(MemPool) is | |
173 | * small; someday we will figure out what to do with all the entries here | |
174 | * that are never used or used only once; perhaps we should simply use | |
175 | * malloc() for those? @?@ | |
176 | */ | |
acf5589a | 177 | memDataInit(MEM_4K_BUF, "4K Buffer", 4096, 10); |
178 | memDataInit(MEM_8K_BUF, "8K Buffer", 8192, 10); | |
179 | memDataInit(MEM_ACCESSLOGENTRY, "AccessLogEntry", | |
180 | sizeof(AccessLogEntry), 10); | |
181 | memDataInit(MEM_ACL, "acl", sizeof(acl), 0); | |
182 | memDataInit(MEM_ACLCHECK_T, "aclCheck_t", sizeof(aclCheck_t), 0); | |
183 | memDataInit(MEM_ACL_ACCESS, "acl_access", sizeof(acl_access), 0); | |
184 | memDataInit(MEM_ACL_DENY_INFO_LIST, "acl_deny_info_list", | |
185 | sizeof(acl_deny_info_list), 0); | |
186 | memDataInit(MEM_ACL_IP_DATA, "acl_ip_data", sizeof(acl_ip_data), 0); | |
187 | memDataInit(MEM_ACL_LIST, "acl_list", sizeof(acl_list), 0); | |
188 | memDataInit(MEM_ACL_NAME_LIST, "acl_name_list", sizeof(acl_name_list), 0); | |
189 | memDataInit(MEM_ACL_TIME_DATA, "acl_time_data", sizeof(acl_time_data), 0); | |
190 | memDataInit(MEM_AIO_RESULT_T, "aio_result_t", sizeof(aio_result_t), 0); | |
acf5589a | 191 | memDataInit(MEM_CACHEMGR_PASSWD, "cachemgr_passwd", |
192 | sizeof(cachemgr_passwd), 0); | |
193 | memDataInit(MEM_CLIENTHTTPREQUEST, "clientHttpRequest", | |
194 | sizeof(clientHttpRequest), 0); | |
195 | memDataInit(MEM_CLOSE_HANDLER, "close_handler", sizeof(close_handler), 0); | |
196 | memDataInit(MEM_COMMWRITESTATEDATA, "CommWriteStateData", | |
197 | sizeof(CommWriteStateData), 0); | |
198 | memDataInit(MEM_CONNSTATEDATA, "ConnStateData", sizeof(ConnStateData), 0); | |
199 | memDataInit(MEM_DISK_BUF, "Disk I/O Buffer", DISK_PAGE_SIZE, 200); | |
200 | memDataInit(MEM_DLINK_LIST, "dlink_list", sizeof(dlink_list), 10); | |
201 | memDataInit(MEM_DLINK_NODE, "dlink_node", sizeof(dlink_node), 10); | |
202 | memDataInit(MEM_DNSSERVER_T, "dnsserver_t", sizeof(dnsserver_t), 0); | |
203 | memDataInit(MEM_DNSSTATDATA, "dnsStatData", sizeof(dnsStatData), 0); | |
204 | memDataInit(MEM_DOMAIN_PING, "domain_ping", sizeof(domain_ping), 0); | |
205 | memDataInit(MEM_DOMAIN_TYPE, "domain_type", sizeof(domain_type), 0); | |
206 | memDataInit(MEM_DREAD_CTRL, "dread_ctrl", sizeof(dread_ctrl), 0); | |
207 | memDataInit(MEM_DWRITE_Q, "dwrite_q", sizeof(dwrite_q), 0); | |
208 | memDataInit(MEM_ERRORSTATE, "ErrorState", sizeof(ErrorState), 0); | |
209 | memDataInit(MEM_FILEMAP, "fileMap", sizeof(fileMap), 0); | |
210 | memDataInit(MEM_FQDNCACHE_ENTRY, "fqdncache_entry", | |
211 | sizeof(fqdncache_entry), 0); | |
b817e5e9 | 212 | memDataInit(MEM_FQDNCACHE_PENDING, "fqdn_pending", |
213 | sizeof(fqdn_pending), 0); | |
acf5589a | 214 | memDataInit(MEM_HASH_LINK, "hash_link", sizeof(hash_link), 0); |
215 | memDataInit(MEM_HASH_TABLE, "hash_table", sizeof(hash_table), 0); | |
216 | memDataInit(MEM_HIERARCHYLOGENTRY, "HierarchyLogEntry", | |
217 | sizeof(HierarchyLogEntry), 0); | |
4cc73db3 | 218 | memDataInit(MEM_HTTP_STATE_DATA, "HttpStateData", sizeof(HttpStateData), 0); |
d8b249ef | 219 | memDataInit(MEM_HTTP_REPLY, "HttpReply", sizeof(HttpReply), 0); |
220 | memDataInit(MEM_HTTP_HDR_ENTRY, "HttpHeaderEntry", sizeof(HttpHeaderEntry), 0); | |
7faf2bdb | 221 | memDataInit(MEM_HTTP_HDR_CC, "HttpHdrCc", sizeof(HttpHdrCc), 0); |
eed12adc | 222 | memDataInit(MEM_HTTP_HDR_RANGE_SPEC, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec), 0); |
223 | memDataInit(MEM_HTTP_HDR_RANGE, "HttpHdrRange", sizeof(HttpHdrRange), 0); | |
d76fcfa7 | 224 | memDataInit(MEM_HTTP_HDR_CONTENT_RANGE, "HttpHdrContRange", sizeof(HttpHdrContRange), 0); |
acf5589a | 225 | memDataInit(MEM_ICPUDPDATA, "icpUdpData", sizeof(icpUdpData), 0); |
226 | memDataInit(MEM_ICP_COMMON_T, "icp_common_t", sizeof(icp_common_t), 0); | |
227 | memDataInit(MEM_ICP_PING_DATA, "icp_ping_data", sizeof(icp_ping_data), 0); | |
228 | memDataInit(MEM_INTLIST, "intlist", sizeof(intlist), 0); | |
229 | memDataInit(MEM_IOSTATS, "iostats", sizeof(iostats), 0); | |
59c4d35b | 230 | memDataInit(MEM_IPCACHE_PENDING, "ip_pending", sizeof(ip_pending), 0); |
acf5589a | 231 | memDataInit(MEM_IPCACHE_ENTRY, "ipcache_entry", sizeof(ipcache_entry), 0); |
232 | memDataInit(MEM_MEMOBJECT, "MemObject", sizeof(MemObject), | |
233 | Squid_MaxFD >> 3); | |
234 | memDataInit(MEM_MEM_HDR, "mem_hdr", sizeof(mem_hdr), 0); | |
235 | memDataInit(MEM_MEM_NODE, "mem_node", sizeof(mem_node), 0); | |
acf5589a | 236 | memDataInit(MEM_NETDBENTRY, "netdbEntry", sizeof(netdbEntry), 0); |
237 | memDataInit(MEM_NET_DB_NAME, "net_db_name", sizeof(net_db_name), 0); | |
238 | memDataInit(MEM_NET_DB_PEER, "net_db_peer", sizeof(net_db_peer), 0); | |
239 | memDataInit(MEM_PEER, "peer", sizeof(peer), 0); | |
240 | memDataInit(MEM_PINGERECHODATA, "pingerEchoData", | |
241 | sizeof(pingerEchoData), 0); | |
242 | memDataInit(MEM_PINGERREPLYDATA, "pingerReplyData", | |
243 | sizeof(pingerReplyData), 0); | |
acf5589a | 244 | memDataInit(MEM_PS_STATE, "ps_state", sizeof(ps_state), 0); |
245 | memDataInit(MEM_REFRESH_T, "refresh_t", sizeof(refresh_t), 0); | |
246 | memDataInit(MEM_RELIST, "relist", sizeof(relist), 0); | |
247 | memDataInit(MEM_REQUEST_T, "request_t", sizeof(request_t), | |
248 | Squid_MaxFD >> 3); | |
acf5589a | 249 | memDataInit(MEM_SQUIDCONFIG, "SquidConfig", sizeof(SquidConfig), 0); |
250 | memDataInit(MEM_SQUIDCONFIG2, "SquidConfig2", sizeof(SquidConfig2), 0); | |
251 | memDataInit(MEM_STATCOUNTERS, "StatCounters", sizeof(StatCounters), 0); | |
252 | memDataInit(MEM_STMEM_BUF, "Store Mem Buffer", SM_PAGE_SIZE, | |
253 | Config.Mem.maxSize / SM_PAGE_SIZE); | |
254 | memDataInit(MEM_STOREENTRY, "StoreEntry", sizeof(StoreEntry), 0); | |
255 | memDataInit(MEM_STORE_CLIENT, "store_client", sizeof(store_client), 0); | |
256 | memDataInit(MEM_SWAPDIR, "SwapDir", sizeof(SwapDir), 0); | |
257 | memDataInit(MEM_USHORTLIST, "ushort_list", sizeof(ushortlist), 0); | |
258 | memDataInit(MEM_WORDLIST, "wordlist", sizeof(wordlist), 0); | |
59c4d35b | 259 | memDataInit(MEM_CLIENT_INFO, "ClientInfo", sizeof(ClientInfo), 0); |
7021844c | 260 | /* test that all entries are initialized */ |
acf5589a | 261 | for (t = MEM_NONE + 1; t < MEM_MAX; t++) { |
acf5589a | 262 | /* |
263 | * If you hit this assertion, then you forgot to add a | |
264 | * memDataInit() line for type 't' above. | |
265 | */ | |
7021844c | 266 | assert(MemPools[t]); |
acf5589a | 267 | } |
9fe7e747 | 268 | /* init string pools */ |
269 | for (i = 0; i < mem_str_pool_count; i++) { | |
270 | StrPools[i].pool = memPoolCreate(StrPoolsAttrs[i].name, StrPoolsAttrs[i].obj_size); | |
271 | } | |
22f3fd98 | 272 | cachemgrRegister("mem", |
273 | "Memory Utilization", | |
274 | memStats, 0); | |
acf5589a | 275 | } |
276 | ||
277 | void | |
7021844c | 278 | memClean() |
acf5589a | 279 | { |
9fe7e747 | 280 | memCleanModule(); |
acf5589a | 281 | } |
282 | ||
acf5589a | 283 | int |
284 | memInUse(mem_type type) | |
285 | { | |
b4832aa9 | 286 | return memPoolInUseCount(MemPools[type]); |
acf5589a | 287 | } |
288 | ||
289 | /* ick */ | |
290 | ||
291 | void | |
292 | memFree4K(void *p) | |
293 | { | |
294 | memFree(MEM_4K_BUF, p); | |
295 | } | |
296 | ||
297 | void | |
298 | memFree8K(void *p) | |
299 | { | |
300 | memFree(MEM_8K_BUF, p); | |
301 | } | |
302 | ||
303 | void | |
304 | memFreeDISK(void *p) | |
305 | { | |
306 | memFree(MEM_DISK_BUF, p); | |
307 | } |