Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/leptonica/src/pixalloc.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /*====================================================================* | |
| 2 - Copyright (C) 2001 Leptonica. All rights reserved. | |
| 3 - | |
| 4 - Redistribution and use in source and binary forms, with or without | |
| 5 - modification, are permitted provided that the following conditions | |
| 6 - are met: | |
| 7 - 1. Redistributions of source code must retain the above copyright | |
| 8 - notice, this list of conditions and the following disclaimer. | |
| 9 - 2. Redistributions in binary form must reproduce the above | |
| 10 - copyright notice, this list of conditions and the following | |
| 11 - disclaimer in the documentation and/or other materials | |
| 12 - provided with the distribution. | |
| 13 - | |
| 14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY | |
| 18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
| 23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
| 24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 25 *====================================================================*/ | |
| 26 | |
| 27 /*! | |
| 28 * \file pixalloc.c | |
| 29 * <pre> | |
| 30 * | |
| 31 * Custom memory storage with allocator and deallocator | |
| 32 * | |
| 33 * l_int32 pmsCreate() | |
| 34 * void pmsDestroy() | |
| 35 * void *pmsCustomAlloc() | |
| 36 * void pmsCustomDealloc() | |
| 37 * void *pmsGetAlloc() | |
| 38 * l_int32 pmsGetLevelForAlloc() | |
| 39 * l_int32 pmsGetLevelForDealloc() | |
| 40 * void pmsLogInfo() | |
| 41 * </pre> | |
| 42 */ | |
| 43 | |
| 44 #ifdef HAVE_CONFIG_H | |
| 45 #include <config_auto.h> | |
| 46 #endif /* HAVE_CONFIG_H */ | |
| 47 | |
| 48 #include "allheaders.h" | |
| 49 | |
| 50 /*-------------------------------------------------------------------------* | |
| 51 * Pix Memory Storage * | |
| 52 * * | |
| 53 * This is a simple utility for handling pix memory storage. It is * | |
| 54 * enabled by setting the PixMemoryManager allocators to the functions * | |
| 55 * that are defined here * | |
| 56 * pmsCustomAlloc() * | |
| 57 * pmsCustomDealloc() * | |
| 58 * Use pmsCreate() at the beginning to do the pre-allocation, and * | |
| 59 * pmsDestroy() at the end to clean it up. * | |
| 60 *-------------------------------------------------------------------------*/ | |
| 61 /* | |
| 62 * In the following, the "memory" refers to the image data | |
| 63 * field that is used within the pix. The memory store is a | |
| 64 * continuous block of memory, that is logically divided into | |
| 65 * smaller "chunks" starting with a set at a minimum size, and | |
| 66 * followed by sets of increasing size that are a power of 2 larger | |
| 67 * than the minimum size. You must specify the number of chunks | |
| 68 * of each size. | |
| 69 * | |
| 70 * A requested data chunk, if it exists, is borrowed from the memory | |
| 71 * storage, and returned after use. If the chunk is too small, or | |
| 72 * too large, or if all chunks in the appropriate size range are | |
| 73 * in use, the memory is allocated dynamically and freed after use. | |
| 74 * | |
| 75 * There are four parameters that determine the use of pre-allocated memory: | |
| 76 * | |
| 77 * minsize: any requested chunk smaller than this is allocated | |
| 78 * dynamically and destroyed after use. No preallocated | |
| 79 * memory is used. | |
| 80 * smallest: the size of the smallest pre-allocated memory chunk. | |
| 81 * nlevels: the number of different sizes of data chunks, each a | |
| 82 * power of 2 larger than 'smallest'. | |
| 83 * numalloc: a Numa of size 'nlevels' containing the number of data | |
| 84 * chunks for each size that are in the memory store. | |
| 85 * | |
| 86 * As an example, suppose: | |
| 87 * minsize = 0.5MB | |
| 88 * smallest = 1.0MB | |
| 89 * nlevels = 4 | |
| 90 * numalloc = {10, 5, 5, 5} | |
| 91 * Then the total amount of allocated memory (in MB) is | |
| 92 * 10 * 1 + 5 * 2 + 5 * 4 + 5 * 8 = 80 MB | |
| 93 * Any pix requiring less than 0.5 MB or more than 8 MB of memory will | |
| 94 * not come from the memory store. Instead, it will be dynamically | |
| 95 * allocated and freed after use. | |
| 96 * | |
| 97 * How is this implemented? | |
| 98 * | |
| 99 * At setup, the full data block size is computed and allocated. | |
| 100 * The addresses of the individual chunks are found, and the pointers | |
| 101 * are stored in a set of Ptra (generic pointer arrays), using one Ptra | |
| 102 * for each of the sizes of the chunks. When returning a chunk after | |
| 103 * use, it is necessary to determine from the address which size level | |
| 104 * (ptra) the chunk belongs to. This is done by comparing the address | |
| 105 * of the associated chunk. | |
| 106 * | |
| 107 * In the event that memory chunks need to be dynamically allocated, | |
| 108 * either (1) because they are too small or too large for the memory | |
| 109 * store or (2) because all the pix of that size (i.e., in the | |
| 110 * appropriate level) in the memory store are in use, the | |
| 111 * addresses generated will be outside the pre-allocated block. | |
| 112 * After use they won't be returned to a ptra; instead the deallocator | |
| 113 * will free them. | |
| 114 */ | |
| 115 | |
| 116 /*! Pix memory storage */ | |
| 117 struct PixMemoryStore | |
| 118 { | |
| 119 struct L_Ptraa *paa; /*!< Holds ptrs to allocated memory */ | |
| 120 size_t minsize; /*!< Pix smaller than this (in bytes) */ | |
| 121 /*!< are allocated dynamically */ | |
| 122 size_t smallest; /*!< Smallest mem (in bytes) alloc'd */ | |
| 123 size_t largest; /*!< Larest mem (in bytes) alloc'd */ | |
| 124 size_t nbytes; /*!< Size of allocated block w/ all chunks */ | |
| 125 l_int32 nlevels; /*!< Num of power-of-2 sizes pre-alloc'd */ | |
| 126 size_t *sizes; /*!< Mem sizes at each power-of-2 level */ | |
| 127 l_int32 *allocarray; /*!< Number of mem alloc'd at each size */ | |
| 128 l_uint32 *baseptr; /*!< ptr to allocated array */ | |
| 129 l_uint32 *maxptr; /*!< ptr just beyond allocated memory */ | |
| 130 l_uint32 **firstptr; /*!< array of ptrs to first chunk in size */ | |
| 131 l_int32 *memused; /*!< log: total # of pix used (by level) */ | |
| 132 l_int32 *meminuse; /*!< log: # of pix in use (by level) */ | |
| 133 l_int32 *memmax; /*!< log: max # of pix in use (by level) */ | |
| 134 l_int32 *memempty; /*!< log: # of pix alloc'd because */ | |
| 135 /*!< the store was empty (by level) */ | |
| 136 char *logfile; /*!< log: set to null if no logging */ | |
| 137 }; | |
| 138 typedef struct PixMemoryStore L_PIX_MEM_STORE; | |
| 139 | |
| 140 static L_PIX_MEM_STORE *CustomPMS = NULL; | |
| 141 | |
| 142 | |
| 143 /*! | |
| 144 * \brief pmsCreate() | |
| 145 * | |
| 146 * \param[in] minsize of data chunk that can be supplied by pms | |
| 147 * \param[in] smallest bytes of the smallest pre-allocated data chunk. | |
| 148 * \param[in] numalloc array with the number of data chunks for each | |
| 149 * size that are in the memory store | |
| 150 * \param[in] logfile use for debugging; null otherwise | |
| 151 * \return 0 if OK, 1 on error | |
| 152 * | |
| 153 * <pre> | |
| 154 * Notes: | |
| 155 * (1) This computes the size of the block of memory required | |
| 156 * and allocates it. Each chunk starts on a 32-bit word boundary. | |
| 157 * The chunk sizes are in powers of 2, starting at %smallest, | |
| 158 * and the number of levels and chunks at each level is | |
| 159 * specified by %numalloc. | |
| 160 * (2) This is intended to manage the image data for a small number | |
| 161 * of relatively large pix. The system malloc is expected to | |
| 162 * handle very large numbers of small chunks efficiently. | |
| 163 * (3) Important: set the allocators and call this function | |
| 164 * before any pix have been allocated. Destroy all the pix | |
| 165 * in the normal way before calling pmsDestroy(). | |
| 166 * (4) The pms struct is stored in a static global, so this function | |
| 167 * is not thread-safe. When used, there must be only one thread | |
| 168 * per process. | |
| 169 * </pre> | |
| 170 */ | |
| 171 l_ok | |
| 172 pmsCreate(size_t minsize, | |
| 173 size_t smallest, | |
| 174 NUMA *numalloc, | |
| 175 const char *logfile) | |
| 176 { | |
| 177 l_int32 nlevels, i, j, nbytes; | |
| 178 l_int32 *alloca; | |
| 179 l_float32 nchunks; | |
| 180 l_uint32 *baseptr, *data; | |
| 181 l_uint32 **firstptr; | |
| 182 size_t *sizes; | |
| 183 L_PIX_MEM_STORE *pms; | |
| 184 L_PTRA *pa; | |
| 185 L_PTRAA *paa; | |
| 186 | |
| 187 if (!numalloc) | |
| 188 return ERROR_INT("numalloc not defined", __func__, 1); | |
| 189 numaGetSum(numalloc, &nchunks); | |
| 190 if (nchunks > 1000.0) | |
| 191 L_WARNING("There are %.0f chunks\n", __func__, nchunks); | |
| 192 | |
| 193 pms = (L_PIX_MEM_STORE *)LEPT_CALLOC(1, sizeof(L_PIX_MEM_STORE)); | |
| 194 CustomPMS = pms; | |
| 195 | |
| 196 /* Make sure that minsize and smallest are multiples of 32 bit words */ | |
| 197 if (minsize % 4 != 0) | |
| 198 minsize -= minsize % 4; | |
| 199 pms->minsize = minsize; | |
| 200 nlevels = numaGetCount(numalloc); | |
| 201 pms->nlevels = nlevels; | |
| 202 | |
| 203 if ((sizes = (size_t *)LEPT_CALLOC(nlevels, sizeof(size_t))) == NULL) | |
| 204 return ERROR_INT("sizes not made", __func__, 1); | |
| 205 pms->sizes = sizes; | |
| 206 if (smallest % 4 != 0) | |
| 207 smallest += 4 - (smallest % 4); | |
| 208 pms->smallest = smallest; | |
| 209 for (i = 0; i < nlevels; i++) | |
| 210 sizes[i] = smallest * ((size_t)1 << i); | |
| 211 pms->largest = sizes[nlevels - 1]; | |
| 212 | |
| 213 alloca = numaGetIArray(numalloc); | |
| 214 pms->allocarray = alloca; | |
| 215 if ((paa = ptraaCreate(nlevels)) == NULL) | |
| 216 return ERROR_INT("paa not made", __func__, 1); | |
| 217 pms->paa = paa; | |
| 218 | |
| 219 for (i = 0, nbytes = 0; i < nlevels; i++) | |
| 220 nbytes += alloca[i] * sizes[i]; | |
| 221 pms->nbytes = nbytes; | |
| 222 | |
| 223 if ((baseptr = (l_uint32 *)LEPT_CALLOC(nbytes / 4, sizeof(l_uint32))) | |
| 224 == NULL) | |
| 225 return ERROR_INT("calloc fail for baseptr", __func__, 1); | |
| 226 pms->baseptr = baseptr; | |
| 227 pms->maxptr = baseptr + nbytes / 4; /* just beyond the memory store */ | |
| 228 if ((firstptr = (l_uint32 **)LEPT_CALLOC(nlevels, sizeof(l_uint32 *))) | |
| 229 == NULL) | |
| 230 return ERROR_INT("calloc fail for firstptr", __func__, 1); | |
| 231 pms->firstptr = firstptr; | |
| 232 | |
| 233 data = baseptr; | |
| 234 for (i = 0; i < nlevels; i++) { | |
| 235 if ((pa = ptraCreate(alloca[i])) == NULL) | |
| 236 return ERROR_INT("pa not made", __func__, 1); | |
| 237 ptraaInsertPtra(paa, i, pa); | |
| 238 firstptr[i] = data; | |
| 239 for (j = 0; j < alloca[i]; j++) { | |
| 240 ptraAdd(pa, data); | |
| 241 data += sizes[i] / 4; | |
| 242 } | |
| 243 } | |
| 244 | |
| 245 if (logfile) { | |
| 246 pms->memused = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); | |
| 247 pms->meminuse = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); | |
| 248 pms->memmax = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); | |
| 249 pms->memempty = (l_int32 *)LEPT_CALLOC(nlevels, sizeof(l_int32)); | |
| 250 pms->logfile = stringNew(logfile); | |
| 251 } | |
| 252 | |
| 253 return 0; | |
| 254 } | |
| 255 | |
| 256 | |
| 257 /*! | |
| 258 * \brief pmsDestroy() | |
| 259 * | |
| 260 * <pre> | |
| 261 * Notes: | |
| 262 * (1) Important: call this function at the end of the program, after | |
| 263 * the last pix has been destroyed. | |
| 264 * </pre> | |
| 265 */ | |
| 266 void | |
| 267 pmsDestroy(void) | |
| 268 { | |
| 269 L_PIX_MEM_STORE *pms; | |
| 270 | |
| 271 if ((pms = CustomPMS) == NULL) | |
| 272 return; | |
| 273 | |
| 274 ptraaDestroy(&pms->paa, FALSE, FALSE); /* don't touch the ptrs */ | |
| 275 LEPT_FREE(pms->baseptr); /* free the memory */ | |
| 276 | |
| 277 if (pms->logfile) { | |
| 278 pmsLogInfo(); | |
| 279 LEPT_FREE(pms->logfile); | |
| 280 LEPT_FREE(pms->memused); | |
| 281 LEPT_FREE(pms->meminuse); | |
| 282 LEPT_FREE(pms->memmax); | |
| 283 LEPT_FREE(pms->memempty); | |
| 284 } | |
| 285 | |
| 286 LEPT_FREE(pms->sizes); | |
| 287 LEPT_FREE(pms->allocarray); | |
| 288 LEPT_FREE(pms->firstptr); | |
| 289 LEPT_FREE(pms); | |
| 290 CustomPMS = NULL; | |
| 291 } | |
| 292 | |
| 293 | |
| 294 /*! | |
| 295 * \brief pmsCustomAlloc() | |
| 296 * | |
| 297 * \param[in] nbytes min number of bytes in the chunk to be retrieved | |
| 298 * \return data ptr to chunk | |
| 299 * | |
| 300 * <pre> | |
| 301 * Notes: | |
| 302 * (1) This attempts to find a suitable pre-allocated chunk. | |
| 303 * If not found, it dynamically allocates the chunk. | |
| 304 * (2) If logging is turned on, the allocations that are not taken | |
| 305 * from the memory store, and are at least as large as the | |
| 306 * minimum size the store can handle, are logged to file. | |
| 307 * </pre> | |
| 308 */ | |
| 309 void * | |
| 310 pmsCustomAlloc(size_t nbytes) | |
| 311 { | |
| 312 l_int32 level; | |
| 313 void *data; | |
| 314 L_PIX_MEM_STORE *pms; | |
| 315 L_PTRA *pa; | |
| 316 | |
| 317 if ((pms = CustomPMS) == NULL) | |
| 318 return (void *)ERROR_PTR("pms not defined", __func__, NULL); | |
| 319 | |
| 320 pmsGetLevelForAlloc(nbytes, &level); | |
| 321 | |
| 322 if (level < 0) { /* size range invalid; must alloc */ | |
| 323 if ((data = pmsGetAlloc(nbytes)) == NULL) | |
| 324 return (void *)ERROR_PTR("data not made", __func__, NULL); | |
| 325 } else { /* get from store */ | |
| 326 pa = ptraaGetPtra(pms->paa, level, L_HANDLE_ONLY); | |
| 327 data = ptraRemoveLast(pa); | |
| 328 if (data && pms->logfile) { | |
| 329 pms->memused[level]++; | |
| 330 pms->meminuse[level]++; | |
| 331 if (pms->meminuse[level] > pms->memmax[level]) | |
| 332 pms->memmax[level]++; | |
| 333 } | |
| 334 if (!data) { /* none left at this level */ | |
| 335 data = pmsGetAlloc(nbytes); | |
| 336 if (pms->logfile) | |
| 337 pms->memempty[level]++; | |
| 338 } | |
| 339 } | |
| 340 | |
| 341 return data; | |
| 342 } | |
| 343 | |
| 344 | |
| 345 /*! | |
| 346 * \brief pmsCustomDealloc() | |
| 347 * | |
| 348 * \param[in] data to be freed or returned to the storage | |
| 349 * \return void | |
| 350 */ | |
| 351 void | |
| 352 pmsCustomDealloc(void *data) | |
| 353 { | |
| 354 l_int32 level; | |
| 355 L_PIX_MEM_STORE *pms; | |
| 356 L_PTRA *pa; | |
| 357 | |
| 358 if ((pms = CustomPMS) == NULL) { | |
| 359 L_ERROR("pms not defined\n", __func__); | |
| 360 return; | |
| 361 } | |
| 362 | |
| 363 if (pmsGetLevelForDealloc(data, &level) == 1) { | |
| 364 L_ERROR("level not found\n", __func__); | |
| 365 return; | |
| 366 } | |
| 367 | |
| 368 if (level < 0) { /* no logging; just free the data */ | |
| 369 LEPT_FREE(data); | |
| 370 } else { /* return the data to the store */ | |
| 371 pa = ptraaGetPtra(pms->paa, level, L_HANDLE_ONLY); | |
| 372 ptraAdd(pa, data); | |
| 373 if (pms->logfile) | |
| 374 pms->meminuse[level]--; | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 | |
| 379 /*! | |
| 380 * \brief pmsGetAlloc() | |
| 381 * | |
| 382 * \param[in] nbytes | |
| 383 * \return data | |
| 384 * | |
| 385 * <pre> | |
| 386 * Notes: | |
| 387 * (1) This is called when a request for pix data cannot be | |
| 388 * obtained from the preallocated memory store. After use it | |
| 389 * is freed like normal memory. | |
| 390 * (2) If logging is on, only write out allocs that are as large as | |
| 391 * the minimum size handled by the memory store. | |
| 392 * (3) The C99 platform-independent format specifier for size_t is %zu. | |
| 393 * Windows since at least VC-2015 is conforming; we can now use %zu. | |
| 394 * </pre> | |
| 395 */ | |
| 396 void * | |
| 397 pmsGetAlloc(size_t nbytes) | |
| 398 { | |
| 399 void *data; | |
| 400 FILE *fp; | |
| 401 L_PIX_MEM_STORE *pms; | |
| 402 | |
| 403 if ((pms = CustomPMS) == NULL) | |
| 404 return (void *)ERROR_PTR("pms not defined", __func__, NULL); | |
| 405 | |
| 406 if ((data = (void *)LEPT_CALLOC(nbytes, sizeof(char))) == NULL) | |
| 407 return (void *)ERROR_PTR("data not made", __func__, NULL); | |
| 408 if (pms->logfile && nbytes >= pms->smallest) { | |
| 409 if ((fp = fopenWriteStream(pms->logfile, "a")) != NULL) { | |
| 410 fprintf(fp, "Alloc %zu bytes at %p\n", nbytes, data); | |
| 411 fclose(fp); | |
| 412 } else { | |
| 413 L_ERROR("failed to open stream for %s\n", __func__, pms->logfile); | |
| 414 } | |
| 415 } | |
| 416 return data; | |
| 417 } | |
| 418 | |
| 419 | |
| 420 /*! | |
| 421 * \brief pmsGetLevelForAlloc() | |
| 422 * | |
| 423 * \param[in] nbytes min number of bytes in the chunk to be retrieved | |
| 424 * \param[out] plevel -1 if either too small or too large | |
| 425 * \return 0 if OK, 1 on error | |
| 426 */ | |
| 427 l_ok | |
| 428 pmsGetLevelForAlloc(size_t nbytes, | |
| 429 l_int32 *plevel) | |
| 430 { | |
| 431 l_int32 i; | |
| 432 l_float64 ratio; | |
| 433 L_PIX_MEM_STORE *pms; | |
| 434 | |
| 435 if (!plevel) | |
| 436 return ERROR_INT("&level not defined", __func__, 1); | |
| 437 *plevel = -1; | |
| 438 if ((pms = CustomPMS) == NULL) | |
| 439 return ERROR_INT("pms not defined", __func__, 1); | |
| 440 | |
| 441 if (nbytes < pms->minsize || nbytes > pms->largest) | |
| 442 return 0; /* -1 */ | |
| 443 | |
| 444 ratio = (l_float64)nbytes / (l_float64)(pms->smallest); | |
| 445 for (i = 0; i < pms->nlevels; i++) { | |
| 446 if (ratio <= 1.0) | |
| 447 break; | |
| 448 ratio /= 2.0; | |
| 449 } | |
| 450 *plevel = i; | |
| 451 | |
| 452 return 0; | |
| 453 } | |
| 454 | |
| 455 | |
| 456 /*! | |
| 457 * \brief pmsGetLevelForDealloc() | |
| 458 * | |
| 459 * \param[in] data ptr to memory chunk | |
| 460 * \param[out] plevel level in memory store; -1 if allocated | |
| 461 * outside the store | |
| 462 * \return 0 if OK, 1 on error | |
| 463 */ | |
| 464 l_ok | |
| 465 pmsGetLevelForDealloc(void *data, | |
| 466 l_int32 *plevel) | |
| 467 { | |
| 468 l_int32 i; | |
| 469 l_uint32 *first; | |
| 470 L_PIX_MEM_STORE *pms; | |
| 471 | |
| 472 if (!plevel) | |
| 473 return ERROR_INT("&level not defined", __func__, 1); | |
| 474 *plevel = -1; | |
| 475 if (!data) | |
| 476 return ERROR_INT("data not defined", __func__, 1); | |
| 477 if ((pms = CustomPMS) == NULL) | |
| 478 return ERROR_INT("pms not defined", __func__, 1); | |
| 479 | |
| 480 if (data < (void *)pms->baseptr || data >= (void *)pms->maxptr) | |
| 481 return 0; /* -1 */ | |
| 482 | |
| 483 for (i = 1; i < pms->nlevels; i++) { | |
| 484 first = pms->firstptr[i]; | |
| 485 if (data < (void *)first) | |
| 486 break; | |
| 487 } | |
| 488 *plevel = i - 1; | |
| 489 | |
| 490 return 0; | |
| 491 } | |
| 492 | |
| 493 | |
| 494 /*! | |
| 495 * \brief pmsLogInfo() | |
| 496 */ | |
| 497 void | |
| 498 pmsLogInfo(void) | |
| 499 { | |
| 500 l_int32 i; | |
| 501 L_PIX_MEM_STORE *pms; | |
| 502 | |
| 503 if ((pms = CustomPMS) == NULL) | |
| 504 return; | |
| 505 | |
| 506 lept_stderr("Total number of pix used at each level\n"); | |
| 507 for (i = 0; i < pms->nlevels; i++) | |
| 508 lept_stderr(" Level %d (%zu bytes): %d\n", i, | |
| 509 pms->sizes[i], pms->memused[i]); | |
| 510 | |
| 511 lept_stderr("Max number of pix in use at any time in each level\n"); | |
| 512 for (i = 0; i < pms->nlevels; i++) | |
| 513 lept_stderr(" Level %d (%zu bytes): %d\n", i, | |
| 514 pms->sizes[i], pms->memmax[i]); | |
| 515 | |
| 516 lept_stderr("Number of pix alloc'd because none were available\n"); | |
| 517 for (i = 0; i < pms->nlevels; i++) | |
| 518 lept_stderr(" Level %d (%zu bytes): %d\n", i, | |
| 519 pms->sizes[i], pms->memempty[i]); | |
| 520 } |
