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