├── config.w32 ├── config.m4 ├── php_memtrack.h ├── package.xml ├── README └── memtrack.c /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_ENABLE("memtrack", "Enable memtrack support", "no"); 5 | 6 | if (PHP_MEMTRACK == "yes") { 7 | EXTENSION("memtrack", "memtrack.c"); 8 | } 9 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | 3 | PHP_ARG_ENABLE(memtrack, whether to enable memtrack support, 4 | [ --enable-memtrack Enable memtrack support]) 5 | 6 | 7 | AC_MSG_CHECKING([whether struct mallinfo is present]) 8 | AC_TRY_COMPILE([#include ], [struct mallinfo info;], 9 | [ 10 | AC_MSG_RESULT([yes]) 11 | AC_DEFINE(PHP_MEMTRACK_HAVE_MALLINFO, 1, [Whether struct mallinfo is present]) 12 | ], [ 13 | AC_MSG_RESULT([no]) 14 | ]) 15 | 16 | if test "$PHP_MEMTRACK" != "no"; then 17 | PHP_NEW_EXTENSION(memtrack, memtrack.c, $ext_shared) 18 | fi 19 | -------------------------------------------------------------------------------- /php_memtrack.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2009 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Antony Dovgal | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifndef PHP_MEMTRACK_H 22 | #define PHP_MEMTRACK_H 23 | 24 | #define PHP_MEMTRACK_VERSION "0.2.0-dev" 25 | 26 | extern zend_module_entry memtrack_module_entry; 27 | #define phpext_memtrack_ptr &memtrack_module_entry 28 | 29 | #ifdef ZTS 30 | #include "TSRM.h" 31 | #endif 32 | 33 | ZEND_BEGIN_MODULE_GLOBALS(memtrack) 34 | zend_bool enabled; 35 | long soft_limit; 36 | long hard_limit; 37 | long vm_limit; 38 | char *ignore_functions; 39 | HashTable ignore_funcs_hash; 40 | size_t prev_memory_usage; 41 | int warnings; 42 | ZEND_END_MODULE_GLOBALS(memtrack) 43 | 44 | #ifdef ZTS 45 | #define MEMTRACK_G(v) TSRMG(memtrack_globals_id, zend_memtrack_globals *, v) 46 | #else 47 | #define MEMTRACK_G(v) (memtrack_globals.v) 48 | #endif 49 | 50 | #endif /* PHP_MEMTRACK_H */ 51 | 52 | /* 53 | * Local variables: 54 | * tab-width: 4 55 | * c-basic-offset: 4 56 | * End: 57 | * vim600: noet sw=4 ts=4 fdm=marker 58 | * vim<600: noet sw=4 ts=4 59 | */ 60 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | memtrack 7 | pecl.php.net 8 | PHP extension to watch (unusually high) memory consumption in PHP scripts 9 | 10 | memtrack is a PHP extension that tracks memory consumption in PHP scripts 11 | and produces reports (warnings) when memory usage reaches certain levels 12 | set by the user. 13 | 14 | 15 | Antony Dovgal 16 | tony2001 17 | tony2001@php.net 18 | yes 19 | 20 | 2011-09-27 21 | 22 | 23 | 0.2.1 24 | 0.2.1 25 | 26 | 27 | beta 28 | beta 29 | 30 | PHP 31 | - fixed PECL bug #23826 (memtrack breaks suhosin checks). 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 5.1.3 46 | 6.0.0 47 | 6.0.0 48 | 49 | 50 | 1.4.0b1 51 | 52 | 53 | 54 | memtrack 55 | 56 | 57 | 58 | betabeta 59 | 0.2.00.2.0 60 | 2010-04-26 61 | - added Win32 config file. 62 | - changed vm_limit to use mallinfo() instead of reading /proc. 63 | 64 | 65 | 66 | betabeta 67 | 0.1.00.1.0 68 | 2009-01-23 69 | 70 | - Initial PECL release 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | memtrack PHP extension 2 | ====================== 3 | 4 | 1. How it works 5 | --------------- 6 | 7 | memtrack is a PHP extension that tracks memory consumption in PHP scripts 8 | and produces reports (warnings) when the consumption reaches certain levels 9 | set by the user. 10 | 11 | memtrack replaces default executor function by its own function which 12 | compares memory usage before and after running the original executor, 13 | this way we can tell how much the memory usage has changed. 14 | 15 | 2. Configuration 16 | ---------------- 17 | 18 | The following INI options are available at the moment: 19 | 20 | memtrack.enabled - Boolean flag, which enables or disabled the extension. 21 | Default value is 0, i.e. disabled. 22 | 23 | memtrack.soft_limit - A soft memory limit. The extension produces a warning when a 24 | function reaches it, if the function is not ignored. 25 | Default value is 0. 26 | 27 | memtrack.hard_limit - A hard memory limit. The extension produces a warning when a 28 | function reaches it, whether or not the function is listed 29 | in memtrack.ignore_functions. 30 | Default value is 0. 31 | 32 | memtrack.ignore_functions - A comma- or whitespace-separated list of functions, 33 | which are to be ignored. The values are case-insensitive, 34 | for class methods use Class::method syntax. 35 | 36 | memtrack.vm_limit - Virtual memory size limit (set on a process), which is measured on shutdown only. 37 | The extension produces a warning when the limit is reached. 38 | NB: Available only on Linux. 39 | Default value is 0. 40 | 41 | 3. Examples 42 | ----------- 43 | 44 | # php -d memtrack.enabled=1 -d memtrack.soft_limit=10000 -d memtrack.ignore_functions="" -r '$a = str_repeat("aaaaaaaa", 100000);' 45 | 46 | Warning: [memtrack] [pid 26154] internal function str_repeat() executed in Command line code on line 1 allocated 1048576 bytes in Command line code on line 1 47 | 48 | # /tmp/1.php 49 | 57 | 58 | # php -d memtrack.enabled=1 -d memtrack.soft_limit=1M -d memtrack.ignore_functions="" -d memtrack.vm_limit=3M /tmp/1.php 59 | 60 | Warning: [memtrack] [pid 26177] user function foo() executed in /tmp/1.php on line 7 allocated 4194304 bytes in /tmp/1.php on line 0 61 | Warning: [memtrack] [pid 26177] virtual memory usage on shutdown: 32911360 bytes in Unknown on line 0 62 | 63 | 64 | 4. Compatibility with other extensions 65 | -------------------------------------- 66 | 67 | memtrack is not a Zend extension, hence it doesn't have any extensions compatibility problems. 68 | Though it was noticed that running Zend Optimizer with memtrack produces op_array's without any 69 | information left, so memtrack is unable to fetch function and class names, as well as filenames 70 | and line numbers, which makes memtrack pretty much useless. 71 | 72 | -------------------------------------------------------------------------------- /memtrack.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2009 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Author: Antony Dovgal | 16 | +----------------------------------------------------------------------+ 17 | */ 18 | 19 | /* $Id$ */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | #include "php.h" 26 | #include "php_ini.h" 27 | #include "ext/standard/info.h" 28 | #include "php_memtrack.h" 29 | 30 | #include "zend.h" 31 | #include "zend_API.h" 32 | #include "zend_constants.h" 33 | #include "zend_compile.h" 34 | #include "zend_extensions.h" 35 | 36 | ZEND_DECLARE_MODULE_GLOBALS(memtrack) 37 | 38 | #ifdef COMPILE_DL_MEMTRACK 39 | ZEND_GET_MODULE(memtrack) 40 | #endif 41 | 42 | int memtrack_execute_initialized = 0; 43 | 44 | void (*memtrack_old_execute)(zend_op_array *op_array TSRMLS_DC); 45 | void memtrack_execute(zend_op_array *op_array TSRMLS_DC); 46 | void (*memtrack_old_execute_internal)(zend_execute_data *current_execute_data, int return_value_used TSRMLS_DC); 47 | void memtrack_execute_internal(zend_execute_data *current_execute_data, int return_value_used TSRMLS_DC); 48 | 49 | #ifdef PHP_MEMTRACK_HAVE_MALLINFO 50 | # ifdef HAVE_MALLOC_H 51 | # include 52 | # endif 53 | static int memtrack_get_vm_size(void) /* {{{ */ 54 | { 55 | struct mallinfo info; 56 | 57 | info = mallinfo(); 58 | return info.arena + info.hblkhd; 59 | } 60 | /* }}} */ 61 | #endif 62 | 63 | static char *mt_get_function_name(zend_op_array *op_array TSRMLS_DC) /* {{{ */ 64 | { 65 | char *current_fname = NULL; 66 | char *class_name, *fname; 67 | zend_bool free_fname = 0; 68 | int class_name_len, fname_len; 69 | zend_execute_data *exec_data = EG(current_execute_data); 70 | zend_class_entry *ce; 71 | char *space; 72 | 73 | if (op_array) { 74 | ce = ((zend_function *)op_array)->common.scope; 75 | class_name = ce ? ce->name : ""; 76 | } else { 77 | class_name = get_active_class_name(&space TSRMLS_CC); 78 | } 79 | 80 | if (class_name[0] == '\0') { 81 | if (op_array) { 82 | current_fname = op_array->function_name; 83 | } else { 84 | current_fname = get_active_function_name(TSRMLS_C); 85 | } 86 | } else { 87 | if (op_array) { 88 | fname = op_array->function_name; 89 | } else { 90 | fname = get_active_function_name(TSRMLS_C); 91 | } 92 | if (fname) { 93 | class_name_len = strlen(class_name); 94 | fname_len = strlen(fname); 95 | 96 | current_fname = emalloc(class_name_len + 2 + fname_len + 1); 97 | free_fname = 1; 98 | 99 | memcpy(current_fname, class_name, class_name_len); 100 | memcpy(current_fname + class_name_len, "::", 2); 101 | memcpy(current_fname + class_name_len + 2, fname, fname_len); 102 | current_fname[class_name_len + 2 + fname_len] = '\0'; 103 | } 104 | } 105 | 106 | if (!current_fname) { 107 | current_fname = "main"; 108 | } 109 | 110 | if (!free_fname && !strcmp("main", current_fname)) { 111 | 112 | if (exec_data && exec_data->opline && exec_data->opline->op2.op_type == IS_UNUSED) { 113 | switch (Z_LVAL(exec_data->opline->op2.u.constant)) { 114 | case ZEND_REQUIRE_ONCE: 115 | current_fname = "require_once"; 116 | break; 117 | case ZEND_INCLUDE: 118 | current_fname = "include"; 119 | break; 120 | case ZEND_REQUIRE: 121 | current_fname = "require"; 122 | break; 123 | case ZEND_INCLUDE_ONCE: 124 | current_fname = "include_once"; 125 | break; 126 | case ZEND_EVAL: 127 | current_fname = "eval"; 128 | break; 129 | } 130 | } 131 | } 132 | 133 | if (!free_fname) { 134 | return estrdup(current_fname); 135 | } else { 136 | return current_fname; 137 | } 138 | } 139 | /* }}} */ 140 | 141 | static void php_memtrack_parse_ignore_funcs(TSRMLS_D) /* {{{ */ 142 | { 143 | char *tmp, *for_free, *start = NULL; 144 | int dummy = 1, start_len; 145 | 146 | if (!MEMTRACK_G(ignore_functions) || MEMTRACK_G(ignore_functions)[0] == '\0') { 147 | return; 148 | } 149 | 150 | tmp = estrdup(MEMTRACK_G(ignore_functions)); 151 | for_free = tmp; 152 | while(*tmp) { 153 | switch (*tmp) { 154 | case ' ': 155 | case ',': 156 | if (start) { 157 | *tmp = '\0'; 158 | start_len = strlen(start); 159 | 160 | if (start_len) { 161 | zend_str_tolower(start, start_len); 162 | zend_hash_add(&MEMTRACK_G(ignore_funcs_hash), start, start_len + 1, (void *)&dummy, sizeof(int), NULL); 163 | } 164 | start = NULL; 165 | } 166 | break; 167 | default: 168 | if (!start) { 169 | start = tmp; 170 | } 171 | break; 172 | } 173 | tmp++; 174 | } 175 | if (start) { 176 | start_len = strlen(start); 177 | 178 | if (start_len) { 179 | zend_str_tolower(start, start_len); 180 | zend_hash_add(&MEMTRACK_G(ignore_funcs_hash), start, start_len + 1, (void *)&dummy, sizeof(int), NULL); 181 | } 182 | } 183 | efree(for_free); 184 | } 185 | /* }}} */ 186 | 187 | static void php_memtrack_init_globals(zend_memtrack_globals *memtrack_globals) /* {{{ */ 188 | { 189 | memset(memtrack_globals, 0, sizeof(zend_memtrack_globals)); 190 | } 191 | /* }}} */ 192 | 193 | /* {{{ PHP_INI 194 | */ 195 | PHP_INI_BEGIN() 196 | STD_PHP_INI_ENTRY("memtrack.enabled", "0", PHP_INI_SYSTEM, OnUpdateBool, enabled, zend_memtrack_globals, memtrack_globals) 197 | STD_PHP_INI_ENTRY("memtrack.soft_limit", "0", PHP_INI_ALL, OnUpdateLong, soft_limit, zend_memtrack_globals, memtrack_globals) 198 | STD_PHP_INI_ENTRY("memtrack.hard_limit", "0", PHP_INI_ALL, OnUpdateLong, hard_limit, zend_memtrack_globals, memtrack_globals) 199 | #ifdef PHP_MEMTRACK_HAVE_MALLINFO 200 | STD_PHP_INI_ENTRY("memtrack.vm_limit", "0", PHP_INI_ALL, OnUpdateLong, vm_limit, zend_memtrack_globals, memtrack_globals) 201 | #endif 202 | STD_PHP_INI_ENTRY("memtrack.ignore_functions", "", PHP_INI_SYSTEM, OnUpdateString, ignore_functions, zend_memtrack_globals, memtrack_globals) 203 | PHP_INI_END() 204 | /* }}} */ 205 | 206 | /* {{{ PHP_MINIT_FUNCTION 207 | */ 208 | PHP_MINIT_FUNCTION(memtrack) 209 | { 210 | ZEND_INIT_MODULE_GLOBALS(memtrack, php_memtrack_init_globals, NULL); 211 | 212 | REGISTER_INI_ENTRIES(); 213 | 214 | return SUCCESS; 215 | } 216 | /* }}} */ 217 | 218 | /* {{{ PHP_MSHUTDOWN_FUNCTION 219 | */ 220 | PHP_MSHUTDOWN_FUNCTION(memtrack) 221 | { 222 | UNREGISTER_INI_ENTRIES(); 223 | 224 | if (memtrack_execute_initialized) { 225 | zend_execute = memtrack_old_execute; 226 | zend_execute_internal = memtrack_old_execute_internal; 227 | } 228 | return SUCCESS; 229 | } 230 | /* }}} */ 231 | 232 | /* {{{ PHP_RINIT_FUNCTION 233 | */ 234 | PHP_RINIT_FUNCTION(memtrack) 235 | { 236 | if (!MEMTRACK_G(enabled)) { 237 | return SUCCESS; 238 | } 239 | 240 | zend_hash_init(&MEMTRACK_G(ignore_funcs_hash), 16, NULL, NULL, 0); 241 | 242 | if (!memtrack_execute_initialized) { 243 | memtrack_old_execute = zend_execute; 244 | zend_execute = memtrack_execute; 245 | 246 | memtrack_old_execute_internal = zend_execute_internal; 247 | zend_execute_internal = memtrack_execute_internal; 248 | memtrack_execute_initialized = 1; 249 | } 250 | 251 | php_memtrack_parse_ignore_funcs(TSRMLS_C); 252 | return SUCCESS; 253 | } 254 | /* }}} */ 255 | 256 | /* {{{ PHP_RSHUTDOWN_FUNCTION 257 | */ 258 | PHP_RSHUTDOWN_FUNCTION(memtrack) 259 | { 260 | if (!MEMTRACK_G(enabled)) { 261 | return SUCCESS; 262 | } 263 | 264 | zend_hash_destroy(&MEMTRACK_G(ignore_funcs_hash)); 265 | 266 | #ifdef PHP_MEMTRACK_HAVE_MALLINFO 267 | if (MEMTRACK_G(vm_limit) > 0) { 268 | int vmsize = memtrack_get_vm_size(); 269 | 270 | if (vmsize > 0 && vmsize >= MEMTRACK_G(vm_limit)) { 271 | zend_error(E_CORE_WARNING, "[memtrack] [pid %d] virtual memory usage on shutdown: %d bytes", getpid(), vmsize); 272 | } 273 | } 274 | #endif 275 | return SUCCESS; 276 | } 277 | /* }}} */ 278 | 279 | /* {{{ PHP_MINFO_FUNCTION 280 | */ 281 | PHP_MINFO_FUNCTION(memtrack) 282 | { 283 | php_info_print_table_start(); 284 | php_info_print_table_header(2, "memtrack support", "enabled"); 285 | php_info_print_table_row(2, "Revision", "$Revision$"); 286 | php_info_print_table_end(); 287 | 288 | DISPLAY_INI_ENTRIES(); 289 | } 290 | /* }}} */ 291 | 292 | /* {{{ memtrack_functions[] 293 | */ 294 | zend_function_entry memtrack_functions[] = { 295 | {NULL, NULL, NULL} 296 | }; 297 | /* }}} */ 298 | 299 | /* {{{ memtrack_module_entry 300 | */ 301 | zend_module_entry memtrack_module_entry = { 302 | #if ZEND_MODULE_API_NO >= 20010901 303 | STANDARD_MODULE_HEADER, 304 | #endif 305 | "memtrack", 306 | memtrack_functions, 307 | PHP_MINIT(memtrack), 308 | PHP_MSHUTDOWN(memtrack), 309 | PHP_RINIT(memtrack), 310 | PHP_RSHUTDOWN(memtrack), 311 | PHP_MINFO(memtrack), 312 | #if ZEND_MODULE_API_NO >= 20010901 313 | PHP_MEMTRACK_VERSION, 314 | #endif 315 | STANDARD_MODULE_PROPERTIES 316 | }; 317 | /* }}} */ 318 | 319 | void memtrack_execute(zend_op_array *op_array TSRMLS_DC) /* {{{ */ 320 | { 321 | if (MEMTRACK_G(soft_limit) <= 0 && MEMTRACK_G(hard_limit) <= 0) { 322 | memtrack_old_execute(op_array TSRMLS_CC); 323 | } else { 324 | size_t memory_usage_start = 0, memory_usage_final = 0; 325 | size_t usage_diff = 0; 326 | 327 | memory_usage_start = zend_memory_usage(1 TSRMLS_CC); 328 | MEMTRACK_G(warnings) = 0; 329 | 330 | memtrack_old_execute(op_array TSRMLS_CC); 331 | memory_usage_final = zend_memory_usage(1 TSRMLS_CC); 332 | 333 | if (MEMTRACK_G(warnings) && memory_usage_final > MEMTRACK_G(prev_memory_usage)) { 334 | usage_diff = memory_usage_final - MEMTRACK_G(prev_memory_usage); 335 | } else if (!MEMTRACK_G(warnings) && memory_usage_final > memory_usage_start) { 336 | usage_diff = memory_usage_final - memory_usage_start; 337 | } 338 | 339 | if (usage_diff >= MEMTRACK_G(soft_limit)) { 340 | char *fname, *lc_fname; 341 | char *filename = (EG(current_execute_data) && EG(current_execute_data)->op_array) ? EG(current_execute_data)->op_array->filename : ""; 342 | int lineno = (EG(current_execute_data) && EG(current_execute_data)->opline) ? EG(current_execute_data)->opline->lineno : 0; 343 | int fname_len; 344 | 345 | fname = mt_get_function_name(op_array TSRMLS_CC); 346 | fname_len = strlen(fname); 347 | 348 | lc_fname = estrndup(fname, fname_len); 349 | zend_str_tolower(lc_fname, fname_len); 350 | 351 | if (usage_diff >= MEMTRACK_G(hard_limit) || zend_hash_exists(&MEMTRACK_G(ignore_funcs_hash), lc_fname, fname_len + 1) == 0) { 352 | zend_error(E_CORE_WARNING, "[memtrack] [pid %d] user function %s() executed in %s on line %d allocated %ld bytes", getpid(), fname, filename, lineno, usage_diff); 353 | MEMTRACK_G(warnings)++; 354 | } 355 | efree(fname); 356 | efree(lc_fname); 357 | } 358 | 359 | MEMTRACK_G(prev_memory_usage) = memory_usage_final; 360 | } 361 | } 362 | /* }}} */ 363 | 364 | void memtrack_execute_internal(zend_execute_data *current_execute_data, int return_value_used TSRMLS_DC) /* {{{ */ 365 | { 366 | if (MEMTRACK_G(soft_limit) <= 0 && MEMTRACK_G(hard_limit) <= 0) { 367 | memtrack_old_execute_internal(current_execute_data, return_value_used TSRMLS_CC); 368 | } else { 369 | size_t memory_usage_start = 0, memory_usage_final = 0; 370 | size_t usage_diff = 0; 371 | 372 | memory_usage_start = zend_memory_usage(1 TSRMLS_CC); 373 | memtrack_old_execute_internal(current_execute_data, return_value_used TSRMLS_CC); 374 | memory_usage_final = zend_memory_usage(1 TSRMLS_CC); 375 | 376 | if (memory_usage_final >= memory_usage_start) { 377 | usage_diff = memory_usage_final - memory_usage_start; 378 | } 379 | 380 | if (usage_diff >= MEMTRACK_G(soft_limit)) { 381 | char *lc_fname, *fname = mt_get_function_name(NULL TSRMLS_CC); 382 | int lineno = (current_execute_data && current_execute_data->opline) ? current_execute_data->opline->lineno : 0; 383 | char *filename = (current_execute_data && current_execute_data->op_array) ? current_execute_data->op_array->filename : "unknown"; 384 | int fname_len; 385 | 386 | fname_len = strlen(fname); 387 | 388 | lc_fname = estrndup(fname, fname_len); 389 | zend_str_tolower(lc_fname, fname_len); 390 | 391 | if (usage_diff >= MEMTRACK_G(hard_limit) || zend_hash_exists(&MEMTRACK_G(ignore_funcs_hash), lc_fname, fname_len + 1) == 0) { 392 | zend_error(E_CORE_WARNING, "[memtrack] [pid %d] internal function %s() executed in %s on line %d allocated %ld bytes", getpid(), fname, filename, lineno, usage_diff); 393 | MEMTRACK_G(warnings)++; 394 | } 395 | efree(fname); 396 | efree(lc_fname); 397 | } 398 | MEMTRACK_G(prev_memory_usage) = memory_usage_final; 399 | } 400 | } 401 | /* }}} */ 402 | 403 | /* 404 | * Local variables: 405 | * tab-width: 4 406 | * c-basic-offset: 4 407 | * End: 408 | * vim600: noet sw=4 ts=4 fdm=marker 409 | * vim<600: noet sw=4 ts=4 410 | */ 411 | --------------------------------------------------------------------------------