3 * $Id: mem.cc,v 1.19 1998/03/20 18:06:45 rousskov 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
14 * the National Science Foundation.
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.
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.
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.
36 static MemPool
*MemPools
[MEM_MAX
];
39 #define mem_str_pool_count 3
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 */
48 static struct { MemPool
*pool
; } StrPools
[mem_str_pool_count
];
49 static MemMeter StrCountMeter
;
50 static MemMeter StrVolumeMeter
;
56 * we have a limit on _total_ amount of idle memory so we ignore
60 memDataInit(mem_type type
, const char *name
, size_t size
, int max_pages_notused
)
63 MemPools
[type
] = memPoolCreate(name
, size
);
67 memStringStats(StoreEntry
* sentry
)
69 const char *pfmt
= "%-20s\t %d\t %d\n";
72 size_t pooled_volume
= 0;
74 storeAppendPrintf(sentry
,
75 "String Pool\t Impact\t\t\n"
76 " \t (%%strings)\t (%%volume)\n");
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
,
83 xpercentInt(plevel
, StrCountMeter
.level
),
84 xpercentInt(plevel
*pool
->obj_size
, StrVolumeMeter
.level
));
85 pooled_count
+= plevel
;
86 pooled_volume
+= plevel
*pool
->obj_size
;
89 storeAppendPrintf(sentry
, pfmt
,
91 xpercentInt(StrCountMeter
.level
-pooled_count
, StrCountMeter
.level
),
92 xpercentInt(StrVolumeMeter
.level
-pooled_volume
, StrVolumeMeter
.level
));
96 memStats(StoreEntry
* sentry
)
100 memStringStats(sentry
);
101 storeBufferFlush(sentry
);
110 /* find appropriate pool and use it (pools always init buffer with 0s) */
112 memAllocate(mem_type type
)
114 return memPoolAlloc(MemPools
[type
]);
117 /* find appropriate pool and use it */
119 memFree(mem_type type
, void *p
)
121 memPoolFree(MemPools
[type
], p
);
124 /* allocate a variable size buffer using best-fit pool */
126 memAllocBuf(size_t net_size
, size_t *gross_size
)
129 MemPool
*pool
= NULL
;
131 for (i
= 0; i
< mem_str_pool_count
; i
++) {
132 if (net_size
<= StrPoolsAttrs
[i
].obj_size
) {
133 pool
= StrPools
[i
].pool
;
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
);
144 /* free buffer allocated with memAllocBuf() */
146 memFreeBuf(size_t size
, void *buf
)
149 MemPool
*pool
= NULL
;
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
;
158 memMeterDec(StrCountMeter
);
159 memMeterDel(StrVolumeMeter
, size
);
160 pool
? memPoolFree(pool
, buf
) : xfree(buf
);
169 /* set all pointers to null */
170 memset(MemPools
, '\0', sizeof(MemPools
));
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? @?@
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);
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);
212 memDataInit(MEM_FQDNCACHE_PENDING
, "fqdn_pending",
213 sizeof(fqdn_pending
), 0);
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);
218 memDataInit(MEM_HTTP_STATE_DATA
, "HttpStateData", sizeof(HttpStateData
), 0);
219 memDataInit(MEM_HTTP_REPLY
, "HttpReply", sizeof(HttpReply
), 0);
220 memDataInit(MEM_HTTP_HDR_ENTRY
, "HttpHeaderEntry", sizeof(HttpHeaderEntry
), 0);
221 memDataInit(MEM_HTTP_HDR_CC
, "HttpHdrCc", sizeof(HttpHdrCc
), 0);
222 memDataInit(MEM_HTTP_HDR_RANGE_SPEC
, "HttpHdrRangeSpec", sizeof(HttpHdrRangeSpec
), 0);
223 memDataInit(MEM_HTTP_HDR_RANGE
, "HttpHdrRange", sizeof(HttpHdrRange
), 0);
224 memDataInit(MEM_HTTP_HDR_CONTENT_RANGE
, "HttpHdrContRange", sizeof(HttpHdrContRange
), 0);
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);
230 memDataInit(MEM_IPCACHE_PENDING
, "ip_pending", sizeof(ip_pending
), 0);
231 memDataInit(MEM_IPCACHE_ENTRY
, "ipcache_entry", sizeof(ipcache_entry
), 0);
232 memDataInit(MEM_MEMOBJECT
, "MemObject", sizeof(MemObject
),
234 memDataInit(MEM_MEM_HDR
, "mem_hdr", sizeof(mem_hdr
), 0);
235 memDataInit(MEM_MEM_NODE
, "mem_node", sizeof(mem_node
), 0);
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);
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
),
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);
259 memDataInit(MEM_CLIENT_INFO
, "ClientInfo", sizeof(ClientInfo
), 0);
260 /* test that all entries are initialized */
261 for (t
= MEM_NONE
+ 1; t
< MEM_MAX
; t
++) {
263 * If you hit this assertion, then you forgot to add a
264 * memDataInit() line for type 't' above.
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
);
272 cachemgrRegister("mem",
273 "Memory Utilization",
284 memInUse(mem_type type
)
286 return memPoolInUseCount(MemPools
[type
]);
294 memFree(MEM_4K_BUF
, p
);
300 memFree(MEM_8K_BUF
, p
);
306 memFree(MEM_DISK_BUF
, p
);