Mercurial > hg > nginx
comparison src/core/ngx_slab.c @ 6828:99770a5ea14f
Slab: slots statistics.
For each slot, the number of total and used entries, as well as
the number of allocation requests and failures, are tracked.
author | Ruslan Ermilov <ru@nginx.com> |
---|---|
date | Wed, 07 Dec 2016 22:25:37 +0300 |
parents | 0e61510c56c4 |
children | 6e757036e588 |
comparison
equal
deleted
inserted
replaced
6827:0e61510c56c4 | 6828:99770a5ea14f |
---|---|
118 slots[i].next = &slots[i]; | 118 slots[i].next = &slots[i]; |
119 slots[i].prev = 0; | 119 slots[i].prev = 0; |
120 } | 120 } |
121 | 121 |
122 p += n * sizeof(ngx_slab_page_t); | 122 p += n * sizeof(ngx_slab_page_t); |
123 size -= n * sizeof(ngx_slab_page_t); | 123 |
124 pool->stats = (ngx_slab_stat_t *) p; | |
125 ngx_memzero(pool->stats, n * sizeof(ngx_slab_stat_t)); | |
126 | |
127 p += n * sizeof(ngx_slab_stat_t); | |
128 | |
129 size -= n * (sizeof(ngx_slab_page_t) + sizeof(ngx_slab_stat_t)); | |
124 | 130 |
125 pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t))); | 131 pages = (ngx_uint_t) (size / (ngx_pagesize + sizeof(ngx_slab_page_t))); |
126 | 132 |
127 pool->pages = (ngx_slab_page_t *) p; | 133 pool->pages = (ngx_slab_page_t *) p; |
128 ngx_memzero(pool->pages, pages * sizeof(ngx_slab_page_t)); | 134 ngx_memzero(pool->pages, pages * sizeof(ngx_slab_page_t)); |
203 } else { | 209 } else { |
204 shift = pool->min_shift; | 210 shift = pool->min_shift; |
205 slot = 0; | 211 slot = 0; |
206 } | 212 } |
207 | 213 |
214 pool->stats[slot].reqs++; | |
215 | |
208 ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, | 216 ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, |
209 "slab alloc: %uz slot: %ui", size, slot); | 217 "slab alloc: %uz slot: %ui", size, slot); |
210 | 218 |
211 slots = ngx_slab_slots(pool); | 219 slots = ngx_slab_slots(pool); |
212 page = slots[slot].next; | 220 page = slots[slot].next; |
230 | 238 |
231 bitmap[n] |= m; | 239 bitmap[n] |= m; |
232 | 240 |
233 i = (n * sizeof(uintptr_t) * 8 + i) << shift; | 241 i = (n * sizeof(uintptr_t) * 8 + i) << shift; |
234 | 242 |
243 p = (uintptr_t) bitmap + i; | |
244 | |
245 pool->stats[slot].used++; | |
246 | |
235 if (bitmap[n] == NGX_SLAB_BUSY) { | 247 if (bitmap[n] == NGX_SLAB_BUSY) { |
236 for (n = n + 1; n < map; n++) { | 248 for (n = n + 1; n < map; n++) { |
237 if (bitmap[n] != NGX_SLAB_BUSY) { | 249 if (bitmap[n] != NGX_SLAB_BUSY) { |
238 p = (uintptr_t) bitmap + i; | |
239 | |
240 goto done; | 250 goto done; |
241 } | 251 } |
242 } | 252 } |
243 | 253 |
244 prev = ngx_slab_page_prev(page); | 254 prev = ngx_slab_page_prev(page); |
246 page->next->prev = page->prev; | 256 page->next->prev = page->prev; |
247 | 257 |
248 page->next = NULL; | 258 page->next = NULL; |
249 page->prev = NGX_SLAB_SMALL; | 259 page->prev = NGX_SLAB_SMALL; |
250 } | 260 } |
251 | |
252 p = (uintptr_t) bitmap + i; | |
253 | 261 |
254 goto done; | 262 goto done; |
255 } | 263 } |
256 } | 264 } |
257 } | 265 } |
273 page->next = NULL; | 281 page->next = NULL; |
274 page->prev = NGX_SLAB_EXACT; | 282 page->prev = NGX_SLAB_EXACT; |
275 } | 283 } |
276 | 284 |
277 p = ngx_slab_page_addr(pool, page) + (i << shift); | 285 p = ngx_slab_page_addr(pool, page) + (i << shift); |
286 | |
287 pool->stats[slot].used++; | |
278 | 288 |
279 goto done; | 289 goto done; |
280 } | 290 } |
281 | 291 |
282 } else { /* shift > ngx_slab_exact_shift */ | 292 } else { /* shift > ngx_slab_exact_shift */ |
303 page->prev = NGX_SLAB_BIG; | 313 page->prev = NGX_SLAB_BIG; |
304 } | 314 } |
305 | 315 |
306 p = ngx_slab_page_addr(pool, page) + (i << shift); | 316 p = ngx_slab_page_addr(pool, page) + (i << shift); |
307 | 317 |
318 pool->stats[slot].used++; | |
319 | |
308 goto done; | 320 goto done; |
309 } | 321 } |
310 } | 322 } |
311 | 323 |
312 ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_alloc(): page is busy"); | 324 ngx_slab_error(pool, NGX_LOG_ALERT, "ngx_slab_alloc(): page is busy"); |
337 page->next = &slots[slot]; | 349 page->next = &slots[slot]; |
338 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL; | 350 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL; |
339 | 351 |
340 slots[slot].next = page; | 352 slots[slot].next = page; |
341 | 353 |
354 pool->stats[slot].total += (ngx_pagesize >> shift) - n; | |
355 | |
342 p = ngx_slab_page_addr(pool, page) + (n << shift); | 356 p = ngx_slab_page_addr(pool, page) + (n << shift); |
357 | |
358 pool->stats[slot].used++; | |
343 | 359 |
344 goto done; | 360 goto done; |
345 | 361 |
346 } else if (shift == ngx_slab_exact_shift) { | 362 } else if (shift == ngx_slab_exact_shift) { |
347 | 363 |
349 page->next = &slots[slot]; | 365 page->next = &slots[slot]; |
350 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT; | 366 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT; |
351 | 367 |
352 slots[slot].next = page; | 368 slots[slot].next = page; |
353 | 369 |
370 pool->stats[slot].total += sizeof(uintptr_t) * 8; | |
371 | |
354 p = ngx_slab_page_addr(pool, page); | 372 p = ngx_slab_page_addr(pool, page); |
373 | |
374 pool->stats[slot].used++; | |
355 | 375 |
356 goto done; | 376 goto done; |
357 | 377 |
358 } else { /* shift > ngx_slab_exact_shift */ | 378 } else { /* shift > ngx_slab_exact_shift */ |
359 | 379 |
361 page->next = &slots[slot]; | 381 page->next = &slots[slot]; |
362 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG; | 382 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG; |
363 | 383 |
364 slots[slot].next = page; | 384 slots[slot].next = page; |
365 | 385 |
386 pool->stats[slot].total += ngx_pagesize >> shift; | |
387 | |
366 p = ngx_slab_page_addr(pool, page); | 388 p = ngx_slab_page_addr(pool, page); |
367 | 389 |
390 pool->stats[slot].used++; | |
391 | |
368 goto done; | 392 goto done; |
369 } | 393 } |
370 } | 394 } |
371 | 395 |
372 p = 0; | 396 p = 0; |
397 | |
398 pool->stats[slot].fails++; | |
373 | 399 |
374 done: | 400 done: |
375 | 401 |
376 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, | 402 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, |
377 "slab alloc: %p", (void *) p); | 403 "slab alloc: %p", (void *) p); |
423 void | 449 void |
424 ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) | 450 ngx_slab_free_locked(ngx_slab_pool_t *pool, void *p) |
425 { | 451 { |
426 size_t size; | 452 size_t size; |
427 uintptr_t slab, m, *bitmap; | 453 uintptr_t slab, m, *bitmap; |
428 ngx_uint_t n, type, slot, shift, map; | 454 ngx_uint_t i, n, type, slot, shift, map; |
429 ngx_slab_page_t *slots, *page; | 455 ngx_slab_page_t *slots, *page; |
430 | 456 |
431 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p); | 457 ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, ngx_cycle->log, 0, "slab free: %p", p); |
432 | 458 |
433 if ((u_char *) p < pool->start || (u_char *) p > pool->end) { | 459 if ((u_char *) p < pool->start || (u_char *) p > pool->end) { |
456 n /= sizeof(uintptr_t) * 8; | 482 n /= sizeof(uintptr_t) * 8; |
457 bitmap = (uintptr_t *) | 483 bitmap = (uintptr_t *) |
458 ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1)); | 484 ((uintptr_t) p & ~((uintptr_t) ngx_pagesize - 1)); |
459 | 485 |
460 if (bitmap[n] & m) { | 486 if (bitmap[n] & m) { |
487 slot = shift - pool->min_shift; | |
461 | 488 |
462 if (page->next == NULL) { | 489 if (page->next == NULL) { |
463 slots = ngx_slab_slots(pool); | 490 slots = ngx_slab_slots(pool); |
464 slot = shift - pool->min_shift; | |
465 | 491 |
466 page->next = slots[slot].next; | 492 page->next = slots[slot].next; |
467 slots[slot].next = page; | 493 slots[slot].next = page; |
468 | 494 |
469 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL; | 495 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_SMALL; |
482 goto done; | 508 goto done; |
483 } | 509 } |
484 | 510 |
485 map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); | 511 map = (ngx_pagesize >> shift) / (sizeof(uintptr_t) * 8); |
486 | 512 |
487 for (n = 1; n < map; n++) { | 513 for (i = 1; i < map; i++) { |
488 if (bitmap[n]) { | 514 if (bitmap[i]) { |
489 goto done; | 515 goto done; |
490 } | 516 } |
491 } | 517 } |
492 | 518 |
493 ngx_slab_free_pages(pool, page, 1); | 519 ngx_slab_free_pages(pool, page, 1); |
520 | |
521 pool->stats[slot].total -= (ngx_pagesize >> shift) - n; | |
494 | 522 |
495 goto done; | 523 goto done; |
496 } | 524 } |
497 | 525 |
498 goto chunk_already_free; | 526 goto chunk_already_free; |
506 if ((uintptr_t) p & (size - 1)) { | 534 if ((uintptr_t) p & (size - 1)) { |
507 goto wrong_chunk; | 535 goto wrong_chunk; |
508 } | 536 } |
509 | 537 |
510 if (slab & m) { | 538 if (slab & m) { |
539 slot = ngx_slab_exact_shift - pool->min_shift; | |
540 | |
511 if (slab == NGX_SLAB_BUSY) { | 541 if (slab == NGX_SLAB_BUSY) { |
512 slots = ngx_slab_slots(pool); | 542 slots = ngx_slab_slots(pool); |
513 slot = ngx_slab_exact_shift - pool->min_shift; | |
514 | 543 |
515 page->next = slots[slot].next; | 544 page->next = slots[slot].next; |
516 slots[slot].next = page; | 545 slots[slot].next = page; |
517 | 546 |
518 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT; | 547 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_EXACT; |
525 goto done; | 554 goto done; |
526 } | 555 } |
527 | 556 |
528 ngx_slab_free_pages(pool, page, 1); | 557 ngx_slab_free_pages(pool, page, 1); |
529 | 558 |
559 pool->stats[slot].total -= sizeof(uintptr_t) * 8; | |
560 | |
530 goto done; | 561 goto done; |
531 } | 562 } |
532 | 563 |
533 goto chunk_already_free; | 564 goto chunk_already_free; |
534 | 565 |
543 | 574 |
544 m = (uintptr_t) 1 << ((((uintptr_t) p & (ngx_pagesize - 1)) >> shift) | 575 m = (uintptr_t) 1 << ((((uintptr_t) p & (ngx_pagesize - 1)) >> shift) |
545 + NGX_SLAB_MAP_SHIFT); | 576 + NGX_SLAB_MAP_SHIFT); |
546 | 577 |
547 if (slab & m) { | 578 if (slab & m) { |
579 slot = shift - pool->min_shift; | |
548 | 580 |
549 if (page->next == NULL) { | 581 if (page->next == NULL) { |
550 slots = ngx_slab_slots(pool); | 582 slots = ngx_slab_slots(pool); |
551 slot = shift - pool->min_shift; | |
552 | 583 |
553 page->next = slots[slot].next; | 584 page->next = slots[slot].next; |
554 slots[slot].next = page; | 585 slots[slot].next = page; |
555 | 586 |
556 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG; | 587 page->prev = (uintptr_t) &slots[slot] | NGX_SLAB_BIG; |
562 if (page->slab & NGX_SLAB_MAP_MASK) { | 593 if (page->slab & NGX_SLAB_MAP_MASK) { |
563 goto done; | 594 goto done; |
564 } | 595 } |
565 | 596 |
566 ngx_slab_free_pages(pool, page, 1); | 597 ngx_slab_free_pages(pool, page, 1); |
598 | |
599 pool->stats[slot].total -= ngx_pagesize >> shift; | |
567 | 600 |
568 goto done; | 601 goto done; |
569 } | 602 } |
570 | 603 |
571 goto chunk_already_free; | 604 goto chunk_already_free; |
601 /* not reached */ | 634 /* not reached */ |
602 | 635 |
603 return; | 636 return; |
604 | 637 |
605 done: | 638 done: |
639 | |
640 pool->stats[slot].used--; | |
606 | 641 |
607 ngx_slab_junk(p, size); | 642 ngx_slab_junk(p, size); |
608 | 643 |
609 return; | 644 return; |
610 | 645 |