3 * $Id: mem.cc,v 1.35 1998/11/12 06:28:14 wessels Exp $
5 * DEBUG: section 13 High Level Memory Pool Management
6 * AUTHOR: Harvest Derived
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
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 the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
40 static MemPool
*MemPools
[MEM_MAX
];
43 #define mem_str_pool_count 3
47 } StrPoolsAttrs
[mem_str_pool_count
] = {
51 }, /* to fit rfc1123 and similar */
53 "Medium Strings", 128,
54 }, /* to fit most urls */
61 } StrPools
[mem_str_pool_count
];
62 static MemMeter StrCountMeter
;
63 static MemMeter StrVolumeMeter
;
69 * we have a limit on _total_ amount of idle memory so we ignore
73 memDataInit(mem_type type
, const char *name
, size_t size
, int max_pages_notused
)
76 MemPools
[type
] = memPoolCreate(name
, size
);
80 memStringStats(StoreEntry
* sentry
)
82 const char *pfmt
= "%-20s\t %d\t %d\n";
85 size_t pooled_volume
= 0;
87 storeAppendPrintf(sentry
,
88 "String Pool\t Impact\t\t\n"
89 " \t (%%strings)\t (%%volume)\n");
91 for (i
= 0; i
< mem_str_pool_count
; i
++) {
92 const MemPool
*pool
= StrPools
[i
].pool
;
93 const int plevel
= pool
->meter
.inuse
.level
;
94 storeAppendPrintf(sentry
, pfmt
,
96 xpercentInt(plevel
, StrCountMeter
.level
),
97 xpercentInt(plevel
* pool
->obj_size
, StrVolumeMeter
.level
));
98 pooled_count
+= plevel
;
99 pooled_volume
+= plevel
* pool
->obj_size
;
102 storeAppendPrintf(sentry
, pfmt
,
104 xpercentInt(StrCountMeter
.level
- pooled_count
, StrCountMeter
.level
),
105 xpercentInt(StrVolumeMeter
.level
- pooled_volume
, StrVolumeMeter
.level
));
109 memStats(StoreEntry
* sentry
)
113 memStringStats(sentry
);
114 storeBufferFlush(sentry
);
123 /* find appropriate pool and use it (pools always init buffer with 0s) */
125 memAllocate(mem_type type
)
127 return memPoolAlloc(MemPools
[type
]);
130 /* find appropriate pool and use it */
132 memFree(mem_type type
, void *p
)
134 memPoolFree(MemPools
[type
], p
);
137 /* allocate a variable size buffer using best-fit pool */
139 memAllocBuf(size_t net_size
, size_t * gross_size
)
142 MemPool
*pool
= NULL
;
144 for (i
= 0; i
< mem_str_pool_count
; i
++) {
145 if (net_size
<= StrPoolsAttrs
[i
].obj_size
) {
146 pool
= StrPools
[i
].pool
;
150 *gross_size
= pool
? pool
->obj_size
: net_size
;
151 assert(*gross_size
>= net_size
);
152 memMeterInc(StrCountMeter
);
153 memMeterAdd(StrVolumeMeter
, *gross_size
);
154 return pool
? memPoolAlloc(pool
) : xcalloc(1, net_size
);
157 /* free buffer allocated with memAllocBuf() */
159 memFreeBuf(size_t size
, void *buf
)
162 MemPool
*pool
= NULL
;
164 for (i
= 0; i
< mem_str_pool_count
; i
++) {
165 if (size
<= StrPoolsAttrs
[i
].obj_size
) {
166 assert(size
== StrPoolsAttrs
[i
].obj_size
);
167 pool
= StrPools
[i
].pool
;
171 memMeterDec(StrCountMeter
);
172 memMeterDel(StrVolumeMeter
, size
);
173 pool
? memPoolFree(pool
, buf
) : xfree(buf
);
182 /* set all pointers to null */
183 memset(MemPools
, '\0', sizeof(MemPools
));
185 * it does not hurt much to have a lot of pools since sizeof(MemPool) is
186 * small; someday we will figure out what to do with all the entries here
187 * that are never used or used only once; perhaps we should simply use
188 * malloc() for those? @?@
190 memDataInit(MEM_2K_BUF
, "2K Buffer", 2048, 10);
191 memDataInit(MEM_4K_BUF
, "4K Buffer", 4096, 10);
192 memDataInit(MEM_8K_BUF
, "8K Buffer", 8192, 10);
193 memDataInit(MEM_CLIENT_SOCK_BUF
, "Client Socket Buffer", CLIENT_SOCK_SZ
, 0);
194 memDataInit(MEM_ACCESSLOGENTRY
, "AccessLogEntry",
195 sizeof(AccessLogEntry
), 10);
196 memDataInit(MEM_ACL
, "acl", sizeof(acl
), 0);
197 memDataInit(MEM_ACLCHECK_T
, "aclCheck_t", sizeof(aclCheck_t
), 0);
198 memDataInit(MEM_ACL_ACCESS
, "acl_access", sizeof(acl_access
), 0);
199 memDataInit(MEM_ACL_DENY_INFO_LIST
, "acl_deny_info_list",
200 sizeof(acl_deny_info_list
), 0);
201 memDataInit(MEM_ACL_IP_DATA
, "acl_ip_data", sizeof(acl_ip_data
), 0);
202 memDataInit(MEM_ACL_LIST
, "acl_list", sizeof(acl_list
), 0);
203 memDataInit(MEM_ACL_NAME_LIST
, "acl_name_list", sizeof(acl_name_list
), 0);
204 memDataInit(MEM_ACL_TIME_DATA
, "acl_time_data", sizeof(acl_time_data
), 0);
205 memDataInit(MEM_ACL_PROXY_AUTH_USER
, "acl_proxy_auth_user",
206 sizeof(acl_proxy_auth_user
), 0);
207 memDataInit(MEM_AIO_RESULT_T
, "aio_result_t", sizeof(aio_result_t
), 0);
208 memDataInit(MEM_CACHEMGR_PASSWD
, "cachemgr_passwd",
209 sizeof(cachemgr_passwd
), 0);
210 #if USE_CACHE_DIGESTS
211 memDataInit(MEM_CACHE_DIGEST
, "CacheDigest", sizeof(CacheDigest
), 0);
213 memDataInit(MEM_CLIENTHTTPREQUEST
, "clientHttpRequest",
214 sizeof(clientHttpRequest
), 0);
215 memDataInit(MEM_CLOSE_HANDLER
, "close_handler", sizeof(close_handler
), 0);
216 memDataInit(MEM_COMMWRITESTATEDATA
, "CommWriteStateData",
217 sizeof(CommWriteStateData
), 0);
218 memDataInit(MEM_CONNSTATEDATA
, "ConnStateData", sizeof(ConnStateData
), 0);
219 memDataInit(MEM_DISK_BUF
, "Disk I/O Buffer", DISK_PAGE_SIZE
, 200);
220 memDataInit(MEM_DLINK_LIST
, "dlink_list", sizeof(dlink_list
), 10);
221 memDataInit(MEM_DLINK_NODE
, "dlink_node", sizeof(dlink_node
), 10);
222 memDataInit(MEM_DNSSERVER_T
, "dnsserver_t", sizeof(dnsserver_t
), 0);
223 memDataInit(MEM_DNSSTATDATA
, "dnsStatData", sizeof(dnsStatData
), 0);
224 memDataInit(MEM_DOMAIN_PING
, "domain_ping", sizeof(domain_ping
), 0);
225 memDataInit(MEM_DOMAIN_TYPE
, "domain_type", sizeof(domain_type
), 0);
226 memDataInit(MEM_DREAD_CTRL
, "dread_ctrl", sizeof(dread_ctrl
), 0);
227 memDataInit(MEM_DWRITE_Q
, "dwrite_q", sizeof(dwrite_q
), 0);
228 memDataInit(MEM_ERRORSTATE
, "ErrorState", sizeof(ErrorState
), 0);
229 memDataInit(MEM_FILEMAP
, "fileMap", sizeof(fileMap
), 0);
230 memDataInit(MEM_FQDNCACHE_ENTRY
, "fqdncache_entry",
231 sizeof(fqdncache_entry
), 0);
232 memDataInit(MEM_FQDNCACHE_PENDING
, "fqdn_pending",
233 sizeof(fqdn_pending
), 0);
234 memDataInit(MEM_FWD_STATE
, "FwdState", sizeof(FwdState
), 0);
235 memDataInit(MEM_FWD_SERVER
, "FwdServer", sizeof(FwdServer
), 0);
236 memDataInit(MEM_HASH_LINK
, "hash_link", sizeof(hash_link
), 0);
237 memDataInit(MEM_HASH_TABLE
, "hash_table", sizeof(hash_table
), 0);
238 memDataInit(MEM_HIERARCHYLOGENTRY
, "HierarchyLogEntry",
239 sizeof(HierarchyLogEntry
), 0);
240 memDataInit(MEM_HTTP_STATE_DATA
, "HttpStateData", sizeof(HttpStateData
), 0);
241 memDataInit(MEM_HTTP_REPLY
, "HttpReply", sizeof(HttpReply
), 0);
242 memDataInit(MEM_HTTP_HDR_ENTRY
, "HttpHeaderEntry", sizeof(HttpHeaderEntry
), 0);
243 memDataInit(MEM_HTTP_HDR_CC
, "HttpHdrCc", sizeof(HttpHdrCc
), 0);
244 memDataInit(MEM_HTTP_HDR_RANGE_SPEC
, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec
), 0);
245 memDataInit(MEM_HTTP_HDR_RANGE
, "HttpHdrRange", sizeof(HttpHdrRange
), 0);
246 memDataInit(MEM_HTTP_HDR_CONTENT_RANGE
, "HttpHdrContRange", sizeof(HttpHdrContRange
), 0);
247 memDataInit(MEM_ICPUDPDATA
, "icpUdpData", sizeof(icpUdpData
), 0);
248 memDataInit(MEM_ICP_COMMON_T
, "icp_common_t", sizeof(icp_common_t
), 0);
249 memDataInit(MEM_ICP_PING_DATA
, "ping_data", sizeof(ping_data
), 0);
250 memDataInit(MEM_INTLIST
, "intlist", sizeof(intlist
), 0);
251 memDataInit(MEM_IOSTATS
, "iostats", sizeof(iostats
), 0);
252 memDataInit(MEM_IPCACHE_PENDING
, "ip_pending", sizeof(ip_pending
), 0);
253 memDataInit(MEM_IPCACHE_ENTRY
, "ipcache_entry", sizeof(ipcache_entry
), 0);
254 memDataInit(MEM_MEMOBJECT
, "MemObject", sizeof(MemObject
),
256 memDataInit(MEM_MEM_NODE
, "mem_node", sizeof(mem_node
), 0);
257 memDataInit(MEM_NETDBENTRY
, "netdbEntry", sizeof(netdbEntry
), 0);
258 memDataInit(MEM_NET_DB_NAME
, "net_db_name", sizeof(net_db_name
), 0);
259 memDataInit(MEM_NET_DB_PEER
, "net_db_peer", sizeof(net_db_peer
), 0);
260 #if USE_CACHE_DIGESTS
261 memDataInit(MEM_DIGEST_FETCH_STATE
, "DigestFetchState", sizeof(DigestFetchState
), 0);
263 memDataInit(MEM_PEER
, "peer", sizeof(peer
), 0);
264 memDataInit(MEM_PINGERECHODATA
, "pingerEchoData",
265 sizeof(pingerEchoData
), 0);
266 memDataInit(MEM_PINGERREPLYDATA
, "pingerReplyData",
267 sizeof(pingerReplyData
), 0);
268 memDataInit(MEM_PS_STATE
, "ps_state", sizeof(ps_state
), 0);
269 memDataInit(MEM_REFRESH_T
, "refresh_t", sizeof(refresh_t
), 0);
270 memDataInit(MEM_RELIST
, "relist", sizeof(relist
), 0);
271 memDataInit(MEM_REQUEST_T
, "request_t", sizeof(request_t
),
273 memDataInit(MEM_SQUIDCONFIG
, "SquidConfig", sizeof(SquidConfig
), 0);
274 memDataInit(MEM_SQUIDCONFIG2
, "SquidConfig2", sizeof(SquidConfig2
), 0);
275 memDataInit(MEM_STATCOUNTERS
, "StatCounters", sizeof(StatCounters
), 0);
276 memDataInit(MEM_STMEM_BUF
, "Store Mem Buffer", SM_PAGE_SIZE
,
277 Config
.Mem
.maxSize
/ SM_PAGE_SIZE
);
278 memDataInit(MEM_STOREENTRY
, "StoreEntry", sizeof(StoreEntry
), 0);
279 memDataInit(MEM_STORE_CLIENT
, "store_client", sizeof(store_client
), 0);
280 memDataInit(MEM_SWAPDIR
, "SwapDir", sizeof(SwapDir
), 0);
281 memDataInit(MEM_USHORTLIST
, "ushort_list", sizeof(ushortlist
), 0);
282 memDataInit(MEM_WORDLIST
, "wordlist", sizeof(wordlist
), 0);
283 memDataInit(MEM_CLIENT_INFO
, "ClientInfo", sizeof(ClientInfo
), 0);
284 memDataInit(MEM_MD5_DIGEST
, "MD5 digest", MD5_DIGEST_CHARS
, 0);
285 memDataInit(MEM_HELPER
, "helper", sizeof(helper
), 0);
286 memDataInit(MEM_HELPER_REQUEST
, "helper_request",
287 sizeof(helper_request
), 0);
288 memDataInit(MEM_HELPER_SERVER
, "helper_server",
289 sizeof(helper_server
), 0);
290 /* test that all entries are initialized */
291 for (t
= MEM_NONE
, t
++; t
< MEM_MAX
; t
++) {
292 if (MEM_DONTFREE
== t
)
295 * If you hit this assertion, then you forgot to add a
296 * memDataInit() line for type 't' above.
300 /* init string pools */
301 for (i
= 0; i
< mem_str_pool_count
; i
++) {
302 StrPools
[i
].pool
= memPoolCreate(StrPoolsAttrs
[i
].name
, StrPoolsAttrs
[i
].obj_size
);
304 cachemgrRegister("mem",
305 "Memory Utilization",
316 memInUse(mem_type type
)
318 return memPoolInUseCount(MemPools
[type
]);
326 memFree(MEM_2K_BUF
, p
);
332 memFree(MEM_4K_BUF
, p
);
338 memFree(MEM_8K_BUF
, p
);
344 memFree(MEM_DISK_BUF
, p
);