Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 1481351 Details for
Bug 1626127
glibc: [RFE] Improve malloc performance in low-memory scenarios for threaded arenas.
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
malloc_bad_mmap_pthread.c
malloc_bad_mmap_pthread.c (text/plain), 4.03 KB, created by
Paulo Andrade
on 2018-09-06 15:51:47 UTC
(
hide
)
Description:
malloc_bad_mmap_pthread.c
Filename:
MIME Type:
Creator:
Paulo Andrade
Created:
2018-09-06 15:51:47 UTC
Size:
4.03 KB
patch
obsolete
>/* > * Demonstrate pathological heap state where every malloc() causes > * three failing mmap() requests before succeeding from the main > * arena, resulting in extremely poor performance. > * > * Compile with (e.g.) > * gcc -O3 -g -Wall -std=gnu99 -fPIC -m64 malloc_bad_mmap_pthread.c -lpthread -lrt -o malloc_bad_mmap_pthread > */ > >#include <pthread.h> >#include <stdio.h> >#include <stdlib.h> >#include <string.h> >#include <sys/mman.h> >#include <sys/resource.h> >#include <sys/time.h> >#include <time.h> >#include <unistd.h> > >#define PRE_BLOCKS 1024 >#define MAX_BLOCKS 100000000 > >typedef struct linked_list >{ > struct linked_list* previous; >} linked_list; > >/** Allocate a list of n blocks */ >static linked_list* list_n(int n) >{ > linked_list* previous = NULL; > linked_list* result = NULL; > > for(int count = 0; count < n; ++count) > { > result = malloc(sizeof(linked_list)); > result->previous = previous; > previous = result; > } > > return result; >} > >/** Allocate a list of blocks until malloc fails */ >static linked_list* list_until_fail(int max_blocks) >{ > linked_list* previous = NULL; > linked_list* next = NULL; > int count = 0; > > while(NULL != (next = malloc(sizeof(linked_list)))) > { > next->previous = previous; > previous = next; > ++count; > if(count > max_blocks) > { > printf("malloc still allocating after %d\n", count); > exit(6); > } > } > > printf("Got failure after %d blocks\n", count); > > return previous; >} > >static void free_list(linked_list* list) >{ > while(list) > { > linked_list* previous = list->previous; > free(list); > list = previous; > } >} > >/* Run on another thread, this will force creation of a non-main arena */ >static void* create_nonmain_arena(void* dummy) >{ > (void) dummy; > void* result = malloc(sizeof(linked_list)); > printf("create_nonmain_arena malloc result %p\n", result); > return result; >} > >static void check_performance(int timing_interval) >{ > for(int count = 0; count < 4; ++count) > { > struct timespec start; > clock_gettime(CLOCK_MONOTONIC, &start); > > for(int count = 0; count < timing_interval; ++count) > { > free(malloc(sizeof(linked_list))); > } > > struct timespec current; > clock_gettime(CLOCK_MONOTONIC, ¤t); > double elapsed = current.tv_sec - start.tv_sec + > 1E-9 * (current.tv_nsec - start.tv_nsec); > > printf( > "Last %d mallocs and frees took %f seconds (%.0f mallocs/sec)\n", > timing_interval, elapsed, timing_interval / elapsed); > } >} > >int main(int argc, char* argv[]) >{ > int timing_interval = argc > 1 ? atoi(argv[1]) : 1000; > > /* Check performance in a clean initial state */ > check_performance(timing_interval); > > /* Pre-allocate some blocks in the main arena that we can later free */ > linked_list* pre_list = list_n(PRE_BLOCKS); > > /* Use malloc from another thread to create a non-main arena */ > pthread_t thread; > int error = pthread_create(&thread, NULL, &create_nonmain_arena, NULL); > if(error) > { > printf("pthread_create failed: %s\n", strerror(error)); > exit(1); > } > void* nonmain_malloced; > error = pthread_join(thread, &nonmain_malloced); > if(error) > { > printf("pthread_join failed: %s\n", strerror(error)); > exit(2); > } > printf("thread result %p\n", nonmain_malloced); > > /* Now we've forced creation of a new arena, cap the process > * vmsize to allow us to exhaust the existing heaps. My system > * (Linux RHEL6) allows an RLIMIT_AS below the current vmsize, so > * the easiest value to choose is 0 > */ > struct rlimit rlim; > rlim.rlim_cur = 0; > rlim.rlim_max = RLIM_INFINITY; > if (-1 == setrlimit(RLIMIT_AS, &rlim)) > { > perror("setrlimit"); > exit(5); > } > > /* Exhaust any free lists on both arenas. This should also switch > * the main thread onto the non-main arena > */ > linked_list* final_list = list_until_fail(MAX_BLOCKS); > > printf("freeing pre_list (from main_arena)\n"); > /* Give back the pre_list so main_arena (only) has space) */ > free_list(pre_list); > > /* Now every call to malloc tries the other arena first, then > * attempts to satisfy the request various ways using mmap, then > * falls back to the main-arena. It never tries the main arena > * first. > */ > check_performance(timing_interval); > > free_list(final_list); > free(nonmain_malloced); >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 1626127
: 1481351 |
1481354