Changes in / [74ec742:7831e8fb]
- Location:
- doc/theses/mubeen_zulfiqar_MMath
- Files:
-
- 7 edited
-
allocator.tex (modified) (38 diffs)
-
background.tex (modified) (15 diffs)
-
benchmarks.tex (modified) (12 diffs)
-
conclusion.tex (modified) (3 diffs)
-
intro.tex (modified) (6 diffs)
-
performance.tex (modified) (7 diffs)
-
uw-ethesis-frontpgs.tex (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
doc/theses/mubeen_zulfiqar_MMath/allocator.tex
r74ec742 r7831e8fb 29 29 llheap's design was reviewed and changed multiple times throughout the thesis. 30 30 Some of the rejected designs are discussed because they show the path to the final design (see discussion in \VRef{s:MultipleHeaps}). 31 Note, a few simple tests for a design choice were compared with the current best allocators to determine the viability of a design.31 Note, a few simples tests for a design choice were compared with the current best allocators to determine the viability of a design. 32 32 33 33 … … 37 37 These designs look at the allocation/free \newterm{fastpath}, \ie when an allocation can immediately return free storage or returned storage is not coalesced. 38 38 \paragraph{T:1 model} 39 \VRef[Figure]{f:T1SharedBuckets} shows one heap accessed by multiple kernel threads (KTs) using a bucket array, where smaller bucket sizes are shared among NKTs.40 This design leverages the fact that usually the allocation requests are less than 1024 bytes and there are only a fewdifferent request sizes.39 \VRef[Figure]{f:T1SharedBuckets} shows one heap accessed by multiple kernel threads (KTs) using a bucket array, where smaller bucket sizes are N-shared across KTs. 40 This design leverages the fact that 95\% of allocation requests are less than 1024 bytes and there are only 3--5 different request sizes. 41 41 When KTs $\le$ N, the common bucket sizes are uncontented; 42 42 when KTs $>$ N, the free buckets are contented and latency increases significantly. … … 64 64 65 65 \paragraph{T:H model} 66 \VRef[Figure]{f:THSharedHeaps} shows a fixed number of heaps (N), each a local free pool, where the heaps are sharded (distributed)across the KTs.66 \VRef[Figure]{f:THSharedHeaps} shows a fixed number of heaps (N), each a local free pool, where the heaps are sharded across the KTs. 67 67 A KT can point directly to its assigned heap or indirectly through the corresponding heap bucket. 68 When KT $\le$ N, the heaps might be uncontented;68 When KT $\le$ N, the heaps are uncontented; 69 69 when KTs $>$ N, the heaps are contented. 70 70 In all cases, a KT must acquire/release a lock, contented or uncontented along the fast allocation path because a heap is shared. 71 By increasing N, this approach reduces contention but increases storage (time versus space);71 By adjusting N upwards, this approach reduces contention but increases storage (time versus space); 72 72 however, picking N is workload specific. 73 73 … … 138 138 (See \VRef[Figure]{f:THSharedHeaps} but with a heap bucket per KT and no bucket or local-pool lock.) 139 139 Hence, immediately after a KT starts, its heap is created and just before a KT terminates, its heap is (logically) deleted. 140 \PAB{Heaps are uncontended for a KTs memory operations as every KT has its own thread-local heap which is not shared with any other KT (modulo operations on the global pool and ownership).} 140 Heaps are uncontended for a KTs memory operations to its heap (modulo operations on the global pool and ownership). 141 141 142 142 Problems: 143 143 \begin{itemize} 144 144 \item 145 Need to know when a KT starts/terminates to create/delete its heap.145 Need to know when a KT is starts/terminates to create/delete its heap. 146 146 147 147 \noindent … … 161 161 \noindent 162 162 In many concurrent applications, good performance is achieved with the number of KTs proportional to the number of CPUs. 163 Since the number of CPUs is relatively small, and a heap is alsorelatively small, $\approx$10K bytes (not including any associated freed storage), the worst-case external fragmentation is still small compared to the RAM available on large servers with many CPUs.163 Since the number of CPUs is relatively small, >~1024, and a heap relatively small, $\approx$10K bytes (not including any associated freed storage), the worst-case external fragmentation is still small compared to the RAM available on large servers with many CPUs. 164 164 \item 165 165 There is the same serially-reusable problem with UTs migrating across KTs. … … 171 171 \noindent 172 172 The conclusion from this design exercise is: any atomic fence, atomic instruction (lock free), or lock along the allocation fastpath produces significant slowdown. 173 For the T:1 and T:H models, locking must exist along the allocation fastpath because the buckets or heaps m ightbe shared by multiple threads, even when KTs $\le$ N.173 For the T:1 and T:H models, locking must exist along the allocation fastpath because the buckets or heaps maybe shared by multiple threads, even when KTs $\le$ N. 174 174 For the T:H=CPU and 1:1 models, locking is eliminated along the allocation fastpath. 175 175 However, T:H=CPU has poor operating-system support to determine the CPU id (heap id) and prevent the serially-reusable problem for KTs. 176 176 More operating system support is required to make this model viable, but there is still the serially-reusable problem with user-level threading. 177 So the 1:1 model had no atomic actions along the fastpath and no special operating-system support requirements.177 Leaving the 1:1 model with no atomic actions along the fastpath and no special operating-system support required. 178 178 The 1:1 model still has the serially-reusable problem with user-level threading, which is addressed in \VRef{s:UserlevelThreadingSupport}, and the greatest potential for heap blowup for certain allocation patterns. 179 179 … … 212 212 Ideally latency is $O(1)$ with a small constant. 213 213 214 To obtain $O(1)$ internal latency means no searching on the allocation fastpath andlargely prohibits coalescing, which leads to external fragmentation.214 To obtain $O(1)$ internal latency means no searching on the allocation fastpath, largely prohibits coalescing, which leads to external fragmentation. 215 215 The mitigating factor is that most programs have well behaved allocation patterns, where the majority of allocation operations can be $O(1)$, and heap blowup does not occur without coalescing (although the allocation footprint may be slightly larger). 216 216 … … 257 257 llheap starts by creating an array of $N$ global heaps from storage obtained using @mmap@, where $N$ is the number of computer cores, that persists for program duration. 258 258 There is a global bump-pointer to the next free heap in the array. 259 When this array is exhausted, another array of heapsis allocated.260 There is a global top pointer for a intrusive linked-listto chain free heaps from terminated threads.261 When statistics are turned on, there is a global top pointer for a intrusive linked-listto chain \emph{all} the heaps, which is traversed to accumulate statistics counters across heaps using @malloc_stats@.259 When this array is exhausted, another array is allocated. 260 There is a global top pointer for a heap intrusive link to chain free heaps from terminated threads. 261 When statistics are turned on, there is a global top pointer for a heap intrusive link to chain \emph{all} the heaps, which is traversed to accumulate statistics counters across heaps using @malloc_stats@. 262 262 263 263 When a KT starts, a heap is allocated from the current array for exclusive use by the KT. 264 When a KT terminates, its heap is chained onto the heap free-list for reuse by a new KT, which prevents unbounded growth of number ofheaps.265 The free heaps are stored onstack so hot storage is reused first.266 Preserving all heaps , created during the program lifetime, solves the storage lifetime problemwhen ownership is used.264 When a KT terminates, its heap is chained onto the heap free-list for reuse by a new KT, which prevents unbounded growth of heaps. 265 The free heaps is a stack so hot storage is reused first. 266 Preserving all heaps created during the program lifetime, solves the storage lifetime problem, when ownership is used. 267 267 This approach wastes storage if a large number of KTs are created/terminated at program start and then the program continues sequentially. 268 268 llheap can be configured with object ownership, where an object is freed to the heap from which it is allocated, or object no-ownership, where an object is freed to the KT's current heap. 269 269 270 270 Each heap uses segregated free-buckets that have free objects distributed across 91 different sizes from 16 to 4M. 271 \PAB{All objects in a bucket are of the same size.}272 271 The number of buckets used is determined dynamically depending on the crossover point from @sbrk@ to @mmap@ allocation using @mallopt( M_MMAP_THRESHOLD )@, \ie small objects managed by the program and large objects managed by the operating system. 273 272 Each free bucket of a specific size has the following two lists: … … 287 286 Quantizing is performed using a binary search over the ordered bucket array. 288 287 An optional optimization is fast lookup $O(1)$ for sizes < 64K from a 64K array of type @char@, where each element has an index to the corresponding bucket. 289 The @char@ type restricts the number of bucket sizes to 256. 288 (Type @char@ restricts the number of bucket sizes to 256.) 290 289 For $S$ > 64K, a binary search is used. 291 290 Then, the allocation storage is obtained from the following locations (in order), with increasing latency. … … 382 381 Then the corresponding bucket of the owner thread is computed for the deallocating thread, and the allocation is pushed onto the deallocating thread's bucket. 383 382 384 Finally, the llheap design funnels \label{p:FunnelRoutine} all allocation/deallocation operations through the @malloc@ and @free@ routines, which are the only routines to directly access and manage the internal data structures of the heap.383 Finally, the llheap design funnels \label{p:FunnelRoutine} all allocation/deallocation operations through routines @malloc@/@free@, which are the only routines to directly access and manage the internal data structures of the heap. 385 384 Other allocation operations, \eg @calloc@, @memalign@, and @realloc@, are composed of calls to @malloc@ and possibly @free@, and may manipulate header information after storage is allocated. 386 385 This design simplifies heap-management code during development and maintenance. … … 389 388 \subsection{Alignment} 390 389 391 Most dynamic memory allocationshave a minimum storage alignment for the contained object(s).390 All dynamic memory allocations must have a minimum storage alignment for the contained object(s). 392 391 Often the minimum memory alignment, M, is the bus width (32 or 64-bit) or the largest register (double, long double) or largest atomic instruction (DCAS) or vector data (MMMX). 393 392 In general, the minimum storage alignment is 8/16-byte boundary on 32/64-bit computers. 394 393 For consistency, the object header is normally aligned at this same boundary. 395 Larger alignments must be a power of 2, such aspage alignment (4/8K).394 Larger alignments must be a power of 2, such page alignment (4/8K). 396 395 Any alignment request, N, $\le$ the minimum alignment is handled as a normal allocation with minimal alignment. 397 396 … … 401 400 \end{center} 402 401 The storage between @E@ and @H@ is chained onto the appropriate free list for future allocations. 403 \PAB{The same approach is used for sufficiently large free blocks}, where @E@ is the start of the free block, and any unused storage before @H@ or after the allocated object becomes free storage.402 This approach is also valid within any sufficiently large free block, where @E@ is the start of the free block, and any unused storage before @H@ or after the allocated object becomes free storage. 404 403 In this approach, the aligned address @A@ is the same as the allocated storage address @P@, \ie @P@ $=$ @A@ for all allocation routines, which simplifies deallocation. 405 404 However, if there are a large number of aligned requests, this approach leads to memory fragmentation from the small free areas around the aligned object. … … 408 407 Finally, this approach is incompatible with allocator designs that funnel allocation requests through @malloc@ as it directly manipulates management information within the allocator to optimize the space/time of a request. 409 408 410 Instead, llheap alignment is accomplished by making a \emph{pessimistic } allocation request for sufficient storage to ensure that \emph{both} the alignment and size request are satisfied, \eg:409 Instead, llheap alignment is accomplished by making a \emph{pessimistically} allocation request for sufficient storage to ensure that \emph{both} the alignment and size request are satisfied, \eg: 411 410 \begin{center} 412 411 \input{Alignment2} … … 425 424 \input{Alignment2Impl} 426 425 \end{center} 427 Since @malloc@ has a minimum alignment of @M@, @P@ $\neq$ @A@ only holds for alignments greater than @M@.426 Since @malloc@ has a minimum alignment of @M@, @P@ $\neq$ @A@ only holds for alignments of @M@ or greater. 428 427 When @P@ $\neq$ @A@, the minimum distance between @P@ and @A@ is @M@ bytes, due to the pessimistic storage-allocation. 429 428 Therefore, there is always room for an @M@-byte fake header before @A@. … … 440 439 \label{s:ReallocStickyProperties} 441 440 442 The allocation routine @realloc@ provides a memory-management pattern for shrinking/enlarging an existing allocation, while maintaining some or all of the object data, rather than performing the following steps manually.441 Allocation routine @realloc@ provides a memory-management pattern for shrinking/enlarging an existing allocation, while maintaining some or all of the object data, rather than performing the following steps manually. 443 442 \begin{flushleft} 444 443 \begin{tabular}{ll} … … 461 460 The realloc pattern leverages available storage at the end of an allocation due to bucket sizes, possibly eliminating a new allocation and copying. 462 461 This pattern is not used enough to reduce storage management costs. 463 In fact, if @oaddr@ is @nullptr@, @realloc@ does a @malloc@, so even the initial @malloc@ can be a @realloc@ for consistency in the allocationpattern.462 In fact, if @oaddr@ is @nullptr@, @realloc@ does a @malloc@, so even the initial @malloc@ can be a @realloc@ for consistency in the pattern. 464 463 465 464 The hidden problem for this pattern is the effect of zero fill and alignment with respect to reallocation. 466 465 Are these properties transient or persistent (``sticky'')? 467 For example, when memory is initially allocated by @calloc@ or @memalign@ with zero fill or alignment properties, respectively, what happens when those allocations are given to @realloc@ to change size ?468 That is, if @realloc@ logically extends storage into unused bucket space or allocates new storage to satisfy a size change, are initial allocation properties preserve d?466 For example, when memory is initially allocated by @calloc@ or @memalign@ with zero fill or alignment properties, respectively, what happens when those allocations are given to @realloc@ to change size. 467 That is, if @realloc@ logically extends storage into unused bucket space or allocates new storage to satisfy a size change, are initial allocation properties preserve? 469 468 Currently, allocation properties are not preserved, so subsequent use of @realloc@ storage may cause inefficient execution or errors due to lack of zero fill or alignment. 470 469 This silent problem is unintuitive to programmers and difficult to locate because it is transient. … … 476 475 477 476 To preserve allocation properties requires storing additional information with an allocation, 478 The best available option is the header, where \VRef[Figure]{f:llheapNormalHeader} shows the llheap storage layout.477 The only available location is the header, where \VRef[Figure]{f:llheapNormalHeader} shows the llheap storage layout. 479 478 The header has two data field sized appropriately for 32/64-bit alignment requirements. 480 479 The first field is a union of three values: … … 488 487 \end{description} 489 488 The second field remembers the request size versus the allocation (bucket) size, \eg request 42 bytes which is rounded up to 64 bytes. 490 \PAB{Since programmers think in request sizes rather than allocation sizes, the request size allows better generation of statistics or errors and also helps in memory management.} 489 Since programmers think in request sizes rather than allocation sizes, the request size allows better generation of statistics or errors. 491 490 492 491 \begin{figure} … … 497 496 \end{figure} 498 497 499 \PAB{The low-order 3-bits of the first field are \emph{unused} for any stored values as these values are 16-byte aligned by default, whereas the second field may use all of its bits.} 498 The low-order 3-bits of the first field are \emph{unused} for any stored values, whereas the second field may use all of its bits. 500 499 The 3 unused bits are used to represent mapped allocation, zero filled, and alignment, respectively. 501 500 Note, the alignment bit is not used in the normal header and the zero-filled/mapped bits are not used in the fake header. … … 503 502 If no bits are on, it implies a basic allocation, which is handled quickly; 504 503 otherwise, the bits are analysed and appropriate actions are taken for the complex cases. 505 Since most allocations are basic, th ey will take significantly less time as the memory operations will be donealong the allocation and free fastpath.504 Since most allocations are basic, this implementation results in a significant performance gain along the allocation and free fastpath. 506 505 507 506 … … 515 514 To locate all statistic counters, heaps are linked together in statistics mode, and this list is locked and traversed to sum all counters across heaps. 516 515 Note, the list is locked to prevent errors traversing an active list; 517 \PAB{the statistics counters are not locked and can flicker during accumulation.} 516 the statistics counters are not locked and can flicker during accumulation, which is not an issue with atomic read/write. 518 517 \VRef[Figure]{f:StatiticsOutput} shows an example of statistics output, which covers all allocation operations and information about deallocating storage not owned by a thread. 519 518 No other memory allocator studied provides as comprehensive statistical information. 520 Finally, these statistics were invaluable during the development of this thesis for debugging and verifying correctness andshould be equally valuable to application developers.519 Finally, these statistics were invaluable during the development of this thesis for debugging and verifying correctness, and hence, should be equally valuable to application developers. 521 520 522 521 \begin{figure} … … 548 547 Nevertheless, the checks detect many allocation problems. 549 548 There is an unfortunate problem in detecting unfreed storage because some library routines assume their allocations have life-time duration, and hence, do not free their storage. 550 For example, @printf@ allocates a 1024 -byte buffer on thefirst call and never deletes this buffer.549 For example, @printf@ allocates a 1024 buffer on first call and never deletes this buffer. 551 550 To prevent a false positive for unfreed storage, it is possible to specify an amount of storage that is never freed (see @malloc_unfreed@ \VPageref{p:malloc_unfreed}), and it is subtracted from the total allocate/free difference. 552 551 Determining the amount of never-freed storage is annoying, but once done, any warnings of unfreed storage are application related. 553 552 554 Tests indicate only a 30\% performance decrease when statistics \emph{and} debugging are enabled, and the latency cost for accumulating statistic is mitigated by limited calls, often only one at the end of the program.553 Tests indicate only a 30\% performance increase when statistics \emph{and} debugging are enabled, and the latency cost for accumulating statistic is mitigated by limited calls, often only one at the end of the program. 555 554 556 555 … … 559 558 560 559 The serially-reusable problem (see \VRef{s:AllocationFastpath}) occurs for kernel threads in the ``T:H model, H = number of CPUs'' model and for user threads in the ``1:1'' model, where llheap uses the ``1:1'' model. 561 \PAB{The solution is to prevent interrupts that can result in CPU or KT change during operations that are logically critical sections such as moving free storage from public heap to the private heap.} 560 The solution is to prevent interrupts that can result in CPU or KT change during operations that are logically critical sections. 562 561 Locking these critical sections negates any attempt for a quick fastpath and results in high contention. 563 562 For user-level threading, the serially-reusable problem appears with time slicing for preemptable scheduling, as the signal handler context switches to another user-level thread. 564 Without time slicing, a user thread performing a long computation can prevent the execution of(starve) other threads.565 \PAB{To prevent starvation for a memory-allocation-intensive thread, \ie the time slice always triggers in an allocation critical-section for one thread so the thread never gets time sliced, a thread-local \newterm{rollforward} flag is set in the signal handler when it aborts a time slice.} 563 Without time slicing, a user thread performing a long computation can prevent execution (starve) other threads. 564 To prevent starvation for an allocation-active thread, \ie the time slice always triggers in an allocation critical-section for one thread, a thread-local \newterm{rollforward} flag is set in the signal handler when it aborts a time slice. 566 565 The rollforward flag is tested at the end of each allocation funnel routine (see \VPageref{p:FunnelRoutine}), and if set, it is reset and a volunteer yield (context switch) is performed to allow other threads to execute. 567 566 568 llheap uses two techniques to detect when execution is in an allocation operation or routine called from allocation operation, to abort any time slice during this period. 569 On the slowpath when executing expensive operations, like @sbrk@ or @mmap@, 570 \PAB{interrupts are disabled/enabled by setting kernel-thread-local flags so the signal handler aborts immediately.} 571 \PAB{On the fastpath, disabling/enabling interrupts is too expensive as accessing kernel-thread-local storage can be expensive and not user-thread-safe.} 567 llheap uses two techniques to detect when execution is in a allocation operation or routine called from allocation operation, to abort any time slice during this period. 568 On the slowpath when executing expensive operations, like @sbrk@ or @mmap@, interrupts are disabled/enabled by setting thread-local flags so the signal handler aborts immediately. 569 On the fastpath, disabling/enabling interrupts is too expensive as accessing thread-local storage can be expensive and not thread-safe. 572 570 For example, the ARM processor stores the thread-local pointer in a coprocessor register that cannot perform atomic base-displacement addressing. 573 \PAB{Hence, there is a window between loading the kernel-thread-local pointer from the coprocessor register into a normal register and adding the displacement when a time slice can move a thread.} 574 575 The fast technique (with lower run time cost) is to definea special code section and places all non-interruptible routines in this section.571 Hence, there is a window between loading the thread-local pointer from the coprocessor register into a normal register and adding the displacement when a time slice can move a thread. 572 573 The fast technique defines a special code section and places all non-interruptible routines in this section. 576 574 The linker places all code in this section into a contiguous block of memory, but the order of routines within the block is unspecified. 577 575 Then, the signal handler compares the program counter at the point of interrupt with the the start and end address of the non-interruptible section, and aborts if executing within this section and sets the rollforward flag. … … 579 577 Hence, for correctness, this approach requires inspection of generated assembler code for routines placed in the non-interruptible section. 580 578 This issue is mitigated by the llheap funnel design so only funnel routines and a few statistics routines are placed in the non-interruptible section and their assembler code examined. 581 These techniques are used in both the \uC and \CFA versions of llheap asboth of these systems have user-level threading.579 These techniques are used in both the \uC and \CFA versions of llheap, where both of these systems have user-level threading. 582 580 583 581 … … 589 587 Programs can be statically or dynamically linked. 590 588 \item 591 \PAB{The order in which the linker schedules startup code is poorly supported so cannot be controlled entirely.} 589 The order the linker schedules startup code is poorly supported. 592 590 \item 593 591 Knowing a KT's start and end independently from the KT code is difficult. … … 602 600 Hence, some part of the @sbrk@ area may be used by the default allocator and statistics about allocation operations cannot be correct. 603 601 Furthermore, dynamic linking goes through trampolines, so there is an additional cost along the allocator fastpath for all allocation operations. 604 Testing showed up to a 5\% performance decrease with dynamic linking as compared tostatic linking, even when using @tls_model("initial-exec")@ so the dynamic loader can obtain tighter binding.602 Testing showed up to a 5\% performance increase for dynamic linking over static linking, even when using @tls_model("initial-exec")@ so the dynamic loader can obtain tighter binding. 605 603 606 604 All allocator libraries need to perform startup code to initialize data structures, such as the heap array for llheap. 607 The problem is getting initializ ationdone before the first allocator call.605 The problem is getting initialized done before the first allocator call. 608 606 However, there does not seem to be mechanism to tell either the static or dynamic loader to first perform initialization code before any calls to a loaded library. 609 \PAB{Also, initialization code of other libraries and run-time envoronment may call memory allocation routines such as \lstinline{malloc}.610 So, this creates an even more difficult situation as there is no mechanism to tell either the static or dynamic loader to first perform initialization code of memory allocator before any other initialization that may involve a dynamic memory allocation call.}611 607 As a result, calls to allocation routines occur without initialization. 612 608 To deal with this problem, it is necessary to put a conditional initialization check along the allocation fastpath to trigger initialization (singleton pattern). … … 645 641 Therefore, the constructor is useless for knowing when a KT starts because the KT must reference it, and the allocator does not control the application KT. 646 642 Fortunately, the singleton pattern needed for initializing the program KT also triggers KT allocator initialization, which can then reference @pgm_thread@ to call @threadManager@'s constructor, otherwise its destructor is not called. 647 Now when a KT terminates, @~ThreadManager@ is called to chain it onto the global-heap free-stack, where @pgm_thread@ is set to true only for the program KT.643 Now when a KT terminates, @~ThreadManager@ is called to chained it onto the global-heap free-stack, where @pgm_thread@ is set to true only for the program KT. 648 644 The conditional destructor call prevents closing down the program heap, which must remain available because epilogue code may free more storage. 649 645 … … 664 660 bool traceHeapOff(); $\C{// stop printing allocation/free calls}$ 665 661 \end{lstlisting} 666 This kind of API is necessary to allow concurrent runtime systems to interact with differen tmemory allocators in a consistent way.662 This kind of API is necessary to allow concurrent runtime systems to interact with difference memory allocators in a consistent way. 667 663 668 664 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% … … 716 712 Most allocators use @nullptr@ to indicate an allocation failure, specifically out of memory; 717 713 hence the need to return an alternate value for a zero-sized allocation. 718 A different approach allowed by @C API@is to abort a program when out of memory and return @nullptr@ for a zero-sized allocation.714 A different approach allowed by the C API is to abort a program when out of memory and return @nullptr@ for a zero-sized allocation. 719 715 In theory, notifying the programmer of memory failure allows recovery; 720 716 in practice, it is almost impossible to gracefully recover when out of memory. … … 740 736 \paragraph{\lstinline{void * aalloc( size_t dim, size_t elemSize )}} 741 737 extends @calloc@ for allocating a dynamic array of objects without calculating the total size of array explicitly but \emph{without} zero-filling the memory. 742 @aalloc@ is significantly faster than @calloc@, \PAB{which is the only alternative given by the memory allocation routines}.738 @aalloc@ is significantly faster than @calloc@, which is the only alternative. 743 739 744 740 \noindent\textbf{Usage} … … 829 825 \begin{itemize} 830 826 \item 831 @fd@: file descriptor.827 @fd@: files description. 832 828 \end{itemize} 833 829 It returns the previous file descriptor. … … 836 832 \label{p:malloc_expansion} 837 833 set the amount (bytes) to extend the heap when there is insufficient free storage to service an allocation request. 838 It returns the heap extension size used throughout a program when requesting more memory from the system using @sbrk@ system-call, \ie called once at heap initialization.834 It returns the heap extension size used throughout a program, \ie called once at heap initialization. 839 835 840 836 \paragraph{\lstinline{size_t malloc_mmap_start()}} … … 919 915 \begin{itemize} 920 916 \item 921 naming: \CFA regular and @ttype@ polymorphism (@ttype@ polymorphism in \CFA is similar to \CC variadic templates)is used to encapsulate a wide range of allocation functionality into a single routine name, so programmers do not have to remember multiple routine names for different kinds of dynamic allocations.922 \item 923 named arguments: individual allocation properties are specified using postfix function call, so the programmers do nothave to remember parameter positions in allocation calls.924 \item 925 object size: like the \CFA 's C-interface, programmers do not have to specify object size or cast allocation results.917 naming: \CFA regular and @ttype@ polymorphism is used to encapsulate a wide range of allocation functionality into a single routine name, so programmers do not have to remember multiple routine names for different kinds of dynamic allocations. 918 \item 919 named arguments: individual allocation properties are specified using postfix function call, so programmers do have to remember parameter positions in allocation calls. 920 \item 921 object size: like the \CFA C-style interface, programmers do not have to specify object size or cast allocation results. 926 922 \end{itemize} 927 923 Note, postfix function call is an alternative call syntax, using backtick @`@, where the argument appears before the function name, \eg … … 932 928 duration dur = 3@`@h + 42@`@m + 17@`@s; 933 929 \end{cfa} 930 @ttype@ polymorphism is similar to \CC variadic templates. 934 931 935 932 \paragraph{\lstinline{T * alloc( ... )} or \lstinline{T * alloc( size_t dim, ... )}} 936 is overloaded with a variable number of specific allocation operations, or an integer dimension parameter followed by a variable number of specific allocation operations. 937 \PAB{These allocation operations can be passed as positional arguments when calling \lstinline{alloc} routine.} 933 is overloaded with a variable number of specific allocation routines, or an integer dimension parameter followed by a variable number specific allocation routines. 938 934 A call without parameters returns a dynamically allocated object of type @T@ (@malloc@). 939 935 A call with only the dimension (dim) parameter returns a dynamically allocated array of objects of type @T@ (@aalloc@). … … 984 980 5 5 5 -555819298 -555819298 // two undefined values 985 981 \end{lstlisting} 986 Examples 1 to 3 fill an object with a value or characters.987 Examples 4 to 7 fill an array of objects with values, another array, or part of an array.982 Examples 1 to 3, fill an object with a value or characters. 983 Examples 4 to 7, fill an array of objects with values, another array, or part of an array. 988 984 989 985 \subparagraph{\lstinline{S_resize(T) ?`resize( void * oaddr )}} … … 1019 1015 \subparagraph{\lstinline{S_realloc(T) ?`realloc( T * a ))}} 1020 1016 used to resize, realign, and fill, where the old object data is copied to the new object. 1021 The old object type must be the same as the new object type, since the value is used.1017 The old object type must be the same as the new object type, since the values used. 1022 1018 Note, for @fill@, only the extra space after copying the data from the old object is filled with the given parameter. 1023 1019 For example: … … 1033 1029 \end{lstlisting} 1034 1030 Examples 2 to 3 change the alignment for the initial storage of @i@. 1035 The @13`fill@ inexample 3 does nothing because no extra space is added.1031 The @13`fill@ for example 3 does nothing because no extra space is added. 1036 1032 1037 1033 \begin{cfa}[numbers=left] … … 1048 1044 \end{lstlisting} 1049 1045 Examples 2 to 4 change the array size, alignment and fill for the initial storage of @ia@. 1050 The @13`fill@ inexample 3 does nothing because no extra space is added.1046 The @13`fill@ for example 3 does nothing because no extra space is added. 1051 1047 1052 1048 These \CFA allocation features are used extensively in the development of the \CFA runtime. -
doc/theses/mubeen_zulfiqar_MMath/background.tex
r74ec742 r7831e8fb 36 36 The management data starts with fixed-sized information in the static-data memory that references components in the dynamic-allocation memory. 37 37 The \newterm{storage data} is composed of allocated and freed objects, and \newterm{reserved memory}. 38 Allocated objects (light grey) are variable sized, and a re allocated and maintained by the program;39 \ PAB{\ie only the memory allocator knows the location of allocated storage, not the program.}38 Allocated objects (light grey) are variable sized, and allocated and maintained by the program; 39 \ie only the program knows the location of allocated storage, not the memory allocator. 40 40 \begin{figure}[h] 41 41 \centering … … 49 49 if there are multiple reserved blocks, they are also chained together, usually internally. 50 50 51 \PAB{In some allocator designs, allocated and freed objects have additional management data embedded within them.} 51 Allocated and freed objects typically have additional management data embedded within them. 52 52 \VRef[Figure]{f:AllocatedObject} shows an allocated object with a header, trailer, and alignment padding and spacing around the object. 53 53 The header contains information about the object, \eg size, type, etc. … … 104 104 \VRef[Figure]{f:MemoryFragmentation} shows an example of how a small block of memory fragments as objects are allocated and deallocated over time. 105 105 Blocks of free memory become smaller and non-contiguous making them less useful in serving allocation requests. 106 \PAB{Memory is highly fragmented when most free blocks are unusable because of their sizes.} 106 Memory is highly fragmented when the sizes of most free blocks are unusable. 107 107 For example, \VRef[Figure]{f:Contiguous} and \VRef[Figure]{f:HighlyFragmented} have the same quantity of external fragmentation, but \VRef[Figure]{f:HighlyFragmented} is highly fragmented. 108 108 If there is a request to allocate a large object, \VRef[Figure]{f:Contiguous} is more likely to be able to satisfy it with existing free memory, while \VRef[Figure]{f:HighlyFragmented} likely has to request more memory from the operating system. … … 137 137 The fewer bin-sizes, the fewer lists need to be searched and maintained; 138 138 however, the bin sizes are less likely to closely fit the requested object size, leading to more internal fragmentation. 139 The more bin sizes, the longer the search and the less likely free objects are to be reused, leading to more external fragmentation and potentially heap blowup.139 The more bin-sizes, the longer the search and the less likely free objects are to be reused, leading to more external fragmentation and potentially heap blowup. 140 140 A variation of the binning algorithm allows objects to be allocated to the requested size, but when an object is freed, it is placed on the free list of the next smallest or equal bin-size. 141 141 For example, with bin sizes of 8 and 16 bytes, a request for 12 bytes allocates only 12 bytes, but when the object is freed, it is placed on the 8-byte bin-list. … … 157 157 The principle of locality recognizes that programs tend to reference a small set of data, called a working set, for a certain period of time, where a working set is composed of temporal and spatial accesses~\cite{Denning05}. 158 158 Temporal clustering implies a group of objects are accessed repeatedly within a short time period, while spatial clustering implies a group of objects physically close together (nearby addresses) are accessed repeatedly within a short time period. 159 Temporal locality commonly occurs during an iterative computation with a fix edset of disjoint variables, while spatial locality commonly occurs when traversing an array.159 Temporal locality commonly occurs during an iterative computation with a fix set of disjoint variables, while spatial locality commonly occurs when traversing an array. 160 160 161 161 Hardware takes advantage of temporal and spatial locality through multiple levels of caching, \ie memory hierarchy. … … 328 328 For example, multiple heaps are managed in a pool, starting with a single or a fixed number of heaps that increase\-/decrease depending on contention\-/space issues. 329 329 At creation, a thread is associated with a heap from the pool. 330 \PAB{In some implementations of this model, when the thread attempts an allocation and its associated heap is locked (contention), it scans for an unlocked heap in the pool.} 330 When the thread attempts an allocation and its associated heap is locked (contention), it scans for an unlocked heap in the pool. 331 331 If an unlocked heap is found, the thread changes its association and uses that heap. 332 332 If all heaps are locked, the thread may create a new heap, use it, and then place the new heap into the pool; … … 347 347 The management information in the static zone must be able to locate all heaps in the dynamic zone. 348 348 The management information for the heaps must reside in the dynamic-allocation zone if there are a variable number. 349 Each heap in the dynamic zone is composed of a list of free objects and a pointer to its reserved memory.349 Each heap in the dynamic zone is composed of a list of a free objects and a pointer to its reserved memory. 350 350 An alternative implementation is for all heaps to share one reserved memory, which requires a separate lock for the reserved storage to ensure mutual exclusion when acquiring new memory. 351 351 Because multiple threads can allocate/free/reallocate adjacent storage, all forms of false sharing may occur. … … 361 361 Multiple heaps increase external fragmentation as the ratio of heaps to threads increases, which can lead to heap blowup. 362 362 The external fragmentation experienced by a program with a single heap is now multiplied by the number of heaps, since each heap manages its own free storage and allocates its own reserved memory. 363 \PAB{Additionally, objects freed by one heap cannot be reused by other threads without increasing the cost of the memory operations, except indirectly by returning free memory to the operating system, which can be expensive.} 364 Depending on how the operating system provides dynamic storage to an application, returning storage may be difficult or impossible, \eg the contiguous @sbrk@ area in Unix. 363 Additionally, objects freed by one heap cannot be reused by other threads, except indirectly by returning free memory to the operating system, which can be expensive. 364 (Depending on how the operating system provides dynamic storage to an application, returning storage may be difficult or impossible, \eg the contiguous @sbrk@ area in Unix.) 365 365 In the worst case, a program in which objects are allocated from one heap but deallocated to another heap means these freed objects are never reused. 366 366 … … 384 384 In contrast, the T:H model spreads each thread's objects over a larger area in different heaps. 385 385 Thread heaps can also eliminate allocator-induced active false-sharing, if memory is acquired so it does not overlap at crucial boundaries with memory for another thread's heap. 386 For example, assume page boundaries coincide with cache line boundaries, if a thread heap always acquires pages of memory thenno two threads share a page or cache line unless pointers are passed among them.386 For example, assume page boundaries coincide with cache line boundaries, then if a thread heap always acquires pages of memory, no two threads share a page or cache line unless pointers are passed among them. 387 387 Hence, allocator-induced active false-sharing in \VRef[Figure]{f:AllocatorInducedActiveFalseSharing} cannot occur because the memory for thread heaps never overlaps. 388 388 389 When a thread terminates, there are two options for handling its threadheap.390 First is to free all objects in the threadheap to the global heap and destroy the thread heap.389 When a thread terminates, there are two options for handling its heap. 390 First is to free all objects in the heap to the global heap and destroy the thread heap. 391 391 Second is to place the thread heap on a list of available heaps and reuse it for a new thread in the future. 392 392 Destroying the thread heap immediately may reduce external fragmentation sooner, since all free objects are freed to the global heap and may be reused by other threads. … … 417 417 When the user thread continues on the new kernel thread, it may have pointers into the previous kernel-thread's heap and hold locks associated with it. 418 418 To get the same kernel-thread safety, time slicing must be disabled/\-enabled around these operations, so the user thread cannot jump to another kernel thread. 419 However, eagerly disabling/enabling time-slicing on the allocation/deallocation fast path is expensive, because preemption does not happen that frequently.419 However, eagerly disabling/enabling time-slicing on the allocation/deallocation fast path is expensive, because preemption is rare (10--100 milliseconds). 420 420 Instead, techniques exist to lazily detect this case in the interrupt handler, abort the preemption, and return to the operation so it can complete atomically. 421 421 Occasionally ignoring a preemption should be benign, but a persistent lack of preemption can result in both short and long term starvation. … … 448 448 449 449 \VRef[Figure]{f:MultipleHeapStorageOwnership} shows the effect of ownership on storage layout. 450 (For simplicity ,assume the heaps all use the same size of reserves storage.)450 (For simplicity assume the heaps all use the same size of reserves storage.) 451 451 In contrast to \VRef[Figure]{f:MultipleHeapStorage}, each reserved area used by a heap only contains free storage for that particular heap because threads must return free objects back to the owner heap. 452 452 Again, because multiple threads can allocate/free/reallocate adjacent storage in the same heap, all forms of false sharing may occur. … … 473 473 While the returning thread can batch objects, batching across multiple heaps is complex and there is no obvious time when to push back to the owner heap. 474 474 It is better for returning threads to immediately return to the receiving thread's batch list as the receiving thread has better knowledge when to incorporate the batch list into its free pool. 475 Batching leverages the fact that most allocation patterns use the contention-free fast-path ,so locking on the batch list is rare for both the returning and receiving threads.476 477 It is possible for heaps to steal objects rather than return them and then reallocate these objects againwhen storage runs out on a heap.475 Batching leverages the fact that most allocation patterns use the contention-free fast-path so locking on the batch list is rare for both the returning and receiving threads. 476 477 It is possible for heaps to steal objects rather than return them and reallocating these objects when storage runs out on a heap. 478 478 However, stealing can result in passive false-sharing. 479 479 For example, in \VRef[Figure]{f:AllocatorInducedPassiveFalseSharing}, Object$_2$ may be deallocated to Thread$_2$'s heap initially. … … 485 485 486 486 Bracketing every allocation with headers/trailers can result in significant internal fragmentation, as shown in \VRef[Figure]{f:ObjectHeaders}. 487 Especially if the headers contain redundant management information \PAB{then storing that information is a waste of storage}, \eg object size may be the same for many objects because programs only allocate a small set of object sizes.487 Especially if the headers contain redundant management information, \eg object size may be the same for many objects because programs only allocate a small set of object sizes. 488 488 As well, it can result in poor cache usage, since only a portion of the cache line is holding useful information from the program's perspective. 489 489 Spatial locality can also be negatively affected leading to poor cache locality~\cite{Feng05}: … … 660 660 With local free-lists in containers, as in \VRef[Figure]{f:LocalFreeListWithinContainers}, the container is simply removed from one heap's free list and placed on the new heap's free list. 661 661 Thus, when using local free-lists, the operation of moving containers is reduced from $O(N)$ to $O(1)$. 662 \PAB{The cost that we have to pay for it is to add information to a header, which increases the header size, and therefore internal fragmentation.} 662 The cost is adding information to a header, which increases the header size, and therefore internal fragmentation. 663 663 664 664 \begin{figure} … … 689 689 The main goal of the hybrid approach is to eliminate locking on thread-local allocation/deallocation, while providing ownership to prevent heap blowup. 690 690 In the hybrid approach, a thread first allocates from its private heap and second from its public heap if no free memory exists in the private heap. 691 Similarly, a thread first deallocates an object toits private heap, and second to the public heap.691 Similarly, a thread first deallocates an object its private heap, and second to the public heap. 692 692 Both private and public heaps can allocate/deallocate to/from the global heap if there is no free memory or excess free memory, although an implementation may choose to funnel all interaction with the global heap through one of the heaps. 693 693 Note, deallocation from the private to the public (dashed line) is unlikely because there is no obvious advantages unless the public heap provides the only interface to the global heap. -
doc/theses/mubeen_zulfiqar_MMath/benchmarks.tex
r74ec742 r7831e8fb 12 12 \item[Benchmarks] 13 13 are a suite of application programs (SPEC CPU/WEB) that are exercised in a common way (inputs) to find differences among underlying software implementations associated with an application (compiler, memory allocator, web server, \etc). 14 The applications are suppose dto represent common execution patterns that need to perform well with respect to an underlying software implementation.14 The applications are suppose to represent common execution patterns that need to perform well with respect to an underlying software implementation. 15 15 Benchmarks are often criticized for having overlapping patterns, insufficient patterns, or extraneous code that masks patterns. 16 16 \item[Micro-Benchmarks] … … 26 26 27 27 This thesis designs and examines a new set of micro-benchmarks for memory allocators that test a variety of allocation patterns, each with multiple tuning parameters. 28 The aim of the micro-benchmark suite is to create a set of programs that can evaluate a memory allocator based on the key performance m etrics such as speed, memory overhead, and cache performance.28 The aim of the micro-benchmark suite is to create a set of programs that can evaluate a memory allocator based on the key performance matrices such as speed, memory overhead, and cache performance. 29 29 % These programs can be taken as a standard to benchmark an allocator's basic goals. 30 30 These programs give details of an allocator's memory overhead and speed under certain allocation patterns. 31 The allocation patterns are configurable (adjustment knobs) to observe an allocator's performance across a spectrum allocation patterns, which is seldom possible with benchmark programs.31 The allocation patterns are configurable (adjustment knobs) to observe an allocator's performance across a spectrum of events for a desired allocation pattern, which is seldom possible with benchmark programs. 32 32 Each micro-benchmark program has multiple control knobs specified by command-line arguments. 33 33 34 The new micro-benchmark suite measures performance by allocating dynamic objects and measuring specific m etrics.34 The new micro-benchmark suite measures performance by allocating dynamic objects and measuring specific matrices. 35 35 An allocator's speed is benchmarked in different ways, as are issues like false sharing. 36 36 … … 40 40 Modern memory allocators, such as llheap, must handle multi-threaded programs at the KT and UT level. 41 41 The following multi-threaded micro-benchmarks are presented to give a sense of prior work~\cite{Berger00} at the KT level. 42 None of the prior work address esmulti-threading at the UT level.42 None of the prior work address multi-threading at the UT level. 43 43 44 44 … … 47 47 This benchmark stresses the ability of the allocator to handle different threads allocating and deallocating independently. 48 48 There is no interaction among threads, \ie no object sharing. 49 Each thread repeatedly allocate s100,000 \emph{8-byte} objects then deallocates them in the order they were allocated.50 \PAB{Execution time of the benchmark evaluates its efficiency.} 49 Each thread repeatedly allocate 100,000 \emph{8-byte} objects then deallocates them in the order they were allocated. 50 Runtime of the benchmark evaluates its efficiency. 51 51 52 52 … … 63 63 Before the thread terminates, it passes its array of 10,000 objects to a new child thread to continue the process. 64 64 The number of thread generations varies depending on the thread speed. 65 It calculates memory operations per second as an indicator of thememory allocator's performance.65 It calculates memory operations per second as an indicator of memory allocator's performance. 66 66 67 67 … … 77 77 The churn benchmark measures the runtime speed of an allocator in a multi-threaded scenerio, where each thread extensively allocates and frees dynamic memory. 78 78 Only @malloc@ and @free@ are used to eliminate any extra cost, such as @memcpy@ in @calloc@ or @realloc@. 79 Churn simulates a memory intensive program andcan be tuned to create different scenarios.79 Churn simulates a memory intensive program that can be tuned to create different scenarios. 80 80 81 81 \VRef[Figure]{fig:ChurnBenchFig} shows the pseudo code for the churn micro-benchmark. … … 141 141 Each worker thread allocates an object and intensively reads/writes it for M times to possible invalidate cache lines that may interfere with other threads sharing the same cache line. 142 142 Each thread repeats this for N times. 143 The main thread measures the total time taken for all worker threads to complete.144 Worker threads sharing cache lines with each other are expected totake longer.143 The main thread measures the total time taken to for all worker threads to complete. 144 Worker threads sharing cache lines with each other will take longer. 145 145 146 146 \begin{figure} … … 156 156 signal workers to free 157 157 ... 158 print addresses from each $thread$ 158 159 Worker Thread$\(_1\)$ 159 warm up memory in chunks of 16 bytes160 ...161 For N162 malloc an object163 read/write the object M times164 free the object165 ...160 allocate, write, read, free 161 warmup memory in chunkc of 16 bytes 162 ... 163 malloc N objects 164 ... 165 free objects 166 return object address to Main Thread 166 167 Worker Thread$\(_2\)$ 167 168 // same as Worker Thread$\(_1\)$ … … 190 191 191 192 The cache-scratch micro-benchmark measures allocator-induced passive false-sharing as illustrated in \VRef{s:AllocatorInducedPassiveFalseSharing}. 192 As withcache thrash, if memory is allocated for multiple threads on the same cache line, this can significantly slow down program performance.193 As for cache thrash, if memory is allocated for multiple threads on the same cache line, this can significantly slow down program performance. 193 194 In this scenario, the false sharing is being caused by the memory allocator although it is started by the program sharing an object. 194 195 … … 201 202 Cache scratch tries to create a scenario that leads to false sharing and should make the memory allocator preserve the program-induced false sharing, if it does not return a freed object to its owner thread and, instead, re-uses it instantly. 202 203 An allocator using object ownership, as described in section \VRef{s:Ownership}, is less susceptible to allocator-induced passive false-sharing. 203 \PAB{If the object is returned to the thread that owns it, then the new object that the thread gets is less likely to be on the same cache line.} 204 If the object is returned to the thread who owns it, then the thread that gets a new object is less likely to be on the same cache line. 204 205 205 206 \VRef[Figure]{fig:benchScratchFig} shows the pseudo code for the cache-scratch micro-benchmark. … … 223 224 signal workers to free 224 225 ... 226 print addresses from each $thread$ 225 227 Worker Thread$\(_1\)$ 226 warmup memory in chunks of 16 bytes 227 ... 228 free the object passed by the Main Thread 229 For N 228 allocate, write, read, free 229 warmup memory in chunkc of 16 bytes 230 ... 231 for ( N ) 232 free an object passed by Main Thread 230 233 malloc new object 231 read/write the object M times232 free the object233 ...234 ... 235 free objects 236 return new object addresses to Main Thread 234 237 Worker Thread$\(_2\)$ 235 238 // same as Worker Thread$\(_1\)$ … … 329 332 \VRef[Figure]{fig:MemoryBenchFig} shows the pseudo code for the memory micro-benchmark. 330 333 It creates a producer-consumer scenario with K producer threads and each producer has M consumer threads. 331 A producer has a separate buffer for each consumer and allocates N objects of random sizes following a configurable distribution for each consumer.334 A producer has a separate buffer for each consumer and allocates N objects of random sizes following a settable distribution for each consumer. 332 335 A consumer frees these objects. 333 336 After every memory operation, program memory usage is recorded throughout the runtime. -
doc/theses/mubeen_zulfiqar_MMath/conclusion.tex
r74ec742 r7831e8fb 17 17 % ==================== 18 18 19 The goal of this thesis was to build a low-latency (or high bandwidth) memory allocator for both KT and UT multi-threading systems that is competitive with the best current memory allocatorswhile extending the feature set of existing and new allocator routines.19 The goal of this thesis was to build a low-latency memory allocator for both KT and UT multi-threads systems, which is competitive with the best current memory allocators, while extending the feature set of existing and new allocator routines. 20 20 The new llheap memory-allocator achieves all of these goals, while maintaining and managing sticky allocation information without a performance loss. 21 21 Hence, it becomes possible to use @realloc@ frequently as a safe operation, rather than just occasionally. 22 22 Furthermore, the ability to query sticky properties and information allows programmers to write safer programs, as it is possible to dynamically match allocation styles from unknown library routines that return allocations. 23 23 24 Extending the C allocation API with @resize@, advanced @realloc@, @aalloc@, @amemalign@, and @cmemalign@ means programmers do not have to do these useful allocation operations themselves.24 Extending the C allocation API with @resize@, advanced @realloc@, @aalloc@, @amemalign@, and @cmemalign@ means programmers do not make mistakes writing theses useful allocation operations. 25 25 The ability to use \CFA's advanced type-system (and possibly \CC's too) to have one allocation routine with completely orthogonal sticky properties shows how far the allocation API can be pushed, which increases safety and greatly simplifies programmer's use of dynamic allocation. 26 26 27 27 Providing comprehensive statistics for all allocation operations is invaluable in understanding and debugging a program's dynamic behaviour. 28 No other memory allocator provides suchcomprehensive statistics gathering.28 No other memory allocator provides comprehensive statistics gathering. 29 29 This capability was used extensively during the development of llheap to verify its behaviour. 30 30 As well, providing a debugging mode where allocations are checked, along with internal pre/post conditions and invariants, is extremely useful, especially for students. 31 While not as powerful as the @valgrind@ interpreter, a large number of allocation mistakes are detected.31 While not as powerful as the @valgrind@ interpreter, a large number of allocations mistakes are detected. 32 32 Finally, contention-free statistics gathering and debugging have a low enough cost to be used in production code. 33 33 … … 36 36 37 37 Starting a micro-benchmark test-suite for comparing allocators, rather than relying on a suite of arbitrary programs, has been an interesting challenge. 38 The current micro-benchmarks allow some understand ingof allocator implementation properties without actually looking at the implementation.38 The current micro-benchmarks allow some understand of allocator implementation properties without actually looking at the implementation. 39 39 For example, the memory micro-benchmark quickly identified how several of the allocators work at the global level. 40 40 It was not possible to show how the micro-benchmarks adjustment knobs were used to tune to an interesting test point. … … 45 45 46 46 A careful walk-though of the allocator fastpath should yield additional optimizations for a slight performance gain. 47 In particular, analysingthe implementation of rpmalloc, which is often the fastest allocator,47 In particular, looking at the implementation of rpmalloc, which is often the fastest allocator, 48 48 49 The micro-benchmark project requires more testing and analysis.50 Additional allocation patterns are needed to extract meaningful information about allocators, and within allocation patterns, what are the most usefultuning knobs.49 The micro-benchmarks project requires more testing and analysis. 50 Additional allocations patterns are needed to extract meaningful information about allocators, and within allocation patterns, what are the best tuning knobs. 51 51 Also, identifying ways to visualize the results of the micro-benchmarks is a work in progress. 52 52 53 After llheap is made available on GitHub, interacting with its users to locate problems and improvementswill make llbench a more robust memory allocator.54 As well, feedback from the \uC and \CFA projects, which have adopted llheap for their memory allocator, will provide additional information.53 After llheap is made available on gitHub, interacting with its users to locate problems and improvements, will make llbench a more robust memory allocator. 54 As well, feedback from the \uC and \CFA projects, which have adopted llheap for their memory allocator, will provide additional feedback. -
doc/theses/mubeen_zulfiqar_MMath/intro.tex
r74ec742 r7831e8fb 53 53 When this allocator proves inadequate, programmers often write specialize allocators for specific needs. 54 54 C and \CC allow easy replacement of the default memory allocator with an alternative specialized or general-purpose memory-allocator. 55 Jikes RVM MMTk~\cite{MMTk} provides a similar generalization for the Java virtual machine. 55 (Jikes RVM MMTk~\cite{MMTk} provides a similar generalization for the Java virtual machine.) 56 56 However, high-performance memory-allocators for kernel and user multi-threaded programs are still being designed and improved. 57 57 For this reason, several alternative general-purpose allocators have been written for C/\CC with the goal of scaling in a multi-threaded program~\cite{Berger00,mtmalloc,streamflow,tcmalloc}. … … 65 65 \begin{enumerate}[leftmargin=*] 66 66 \item 67 Implementation of a new stand-alone concurrent low-latency memory-allocator ($\approx$1,200 lines of code) for C/\CC programs using kernel threads (1:1 threading), and specialized versions of the allocator for the programming languages \uC and \CFA using user-level threads running over multiple kernel threads (M:N threading). 67 Implementation of a new stand-lone concurrent low-latency memory-allocator ($\approx$1,200 lines of code) for C/\CC programs using kernel threads (1:1 threading), and specialized versions of the allocator for the programming languages \uC and \CFA using user-level threads running over multiple kernel threads (M:N threading). 68 69 \item 70 Adopt @nullptr@ return for a zero-sized allocation, rather than an actual memory address, which can be passed to @free@. 68 71 69 72 \item … … 101 104 102 105 \item 103 Provide additional heap wrapper functions in \CFA creating a more usableset of allocation operations and properties.106 Provide additional heap wrapper functions in \CFA creating an orthogonal set of allocation operations and properties. 104 107 105 108 \item … … 108 111 \item 109 112 @malloc_alignment( addr )@ returns the alignment of the allocation pointed-to by @addr@. 110 If the allocation is not aligned or @addr@ is the @ NULL@, the minimal alignment is returned.113 If the allocation is not aligned or @addr@ is the @nulladdr@, the minimal alignment is returned. 111 114 \item 112 115 @malloc_zero_fill( addr )@ returns a boolean result indicating if the memory pointed-to by @addr@ is allocated with zero fill, e.g., by @calloc@/@cmemalign@. … … 116 119 @malloc_usable_size( addr )@ returns the usable (total) size of the memory pointed-to by @addr@, i.e., the bin size containing the allocation, where @malloc_size( addr )@ $\le$ @malloc_usable_size( addr )@. 117 120 \end{itemize} 121 122 \item 123 Provide mostly contention-free allocation and free operations via a heap-per-kernel-thread implementation. 118 124 119 125 \item … … 130 136 131 137 \item 132 Provide extensive runtime checks to valid ateallocation operations and identify the amount of unfreed storage at program termination.138 Provide extensive runtime checks to valid allocation operations and identify the amount of unfreed storage at program termination. 133 139 134 140 \item -
doc/theses/mubeen_zulfiqar_MMath/performance.tex
r74ec742 r7831e8fb 3 3 4 4 This chapter uses the micro-benchmarks from \VRef[Chapter]{s:Benchmarks} to test a number of current memory allocators, including llheap. 5 The goal is to see if llheap is competitive with the current ly popularmemory allocators.5 The goal is to see if llheap is competitive with the current best memory allocators. 6 6 7 7 … … 11 11 \begin{itemize} 12 12 \item 13 \textbf{Nasus} AMD EPYC 7662, 64-core socket $\times$ 2, 2.0 GHz, GCC version 9.3.0 14 \item 13 15 \textbf{Algol} Huawei ARM TaiShan 2280 V2 Kunpeng 920, 24-core socket $\times$ 4, 2.6 GHz, GCC version 9.4.0 14 \item15 \textbf{Nasus} AMD EPYC 7662, 64-core socket $\times$ 2, 2.0 GHz, GCC version 9.3.016 16 \end{itemize} 17 17 … … 31 31 32 32 \paragraph{glibc (\textsf{glc})} 33 \cite{glibc} is the default g libc thread-safe allocator.33 \cite{glibc} is the default gcc thread-safe allocator. 34 34 \\ 35 35 \textbf{Version:} Ubuntu GLIBC 2.31-0ubuntu9.7 2.31\\ … … 46 46 47 47 \paragraph{hoard (\textsf{hrd})} 48 \cite{hoard} is a thread-safe allocator that is multi-threaded and us esa heap layer framework. It has per-thread heaps that have thread-local free-lists, and a global shared heap.48 \cite{hoard} is a thread-safe allocator that is multi-threaded and using a heap layer framework. It has per-thread heaps that have thread-local free-lists, and a global shared heap. 49 49 \\ 50 50 \textbf{Version:} 3.13\\ … … 78 78 79 79 \paragraph{tbb malloc (\textsf{tbb})} 80 \cite{tbbmalloc} is a thread-safe allocator that is multi-threaded and uses aprivate heap for each thread.80 \cite{tbbmalloc} is a thread-safe allocator that is multi-threaded and uses private heap for each thread. 81 81 Each private-heap has multiple bins of different sizes. Each bin contains free regions of the same size. 82 82 \\ … … 90 90 \section{Experiments} 91 91 92 Each micro-benchmark is configured and run with each of the allocators,93 \PAB{The less time an allocator takes to complete a benchmark the better so lower in the graphs is better, except for the Memory micro-benchmark graphs.} 92 The each micro-benchmark is configured and run with each of the allocators, 93 The less time an allocator takes to complete a benchmark the better, so lower in the graphs is better. 94 94 All graphs use log scale on the Y-axis, except for the Memory micro-benchmark (see \VRef{s:MemoryMicroBenchmark}). 95 95 … … 231 231 Second is the low-performer group, which includes the rest of the memory allocators. 232 232 These memory allocators have significant program-induced passive false-sharing, where \textsf{hrd}'s is the worst performing allocator. 233 All of the allocators in this group are sharing heaps among threads at some level. 234 235 Interestingly, allocators such as \textsf{hrd} and \textsf{glc} performed well in micro-benchmark cache thrash (see \VRef{sec:cache-thrash-perf}), but, these allocators are among the low performers in the cache scratch. 236 It suggests these allocators do not actively produce false-sharing, but preserve program-induced passive false sharing. 233 All of the allocator's in this group are sharing heaps among threads at some level. 234 235 Interestingly, allocators such as \textsf{hrd} and \textsf{glc} performed well in micro-benchmark cache thrash (see \VRef{sec:cache-thrash-perf}). 236 But, these allocators are among the low performers in the cache scratch. 237 It suggests these allocators do not actively produce false-sharing but preserve program-induced passive false sharing. 237 238 238 239 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -
doc/theses/mubeen_zulfiqar_MMath/uw-ethesis-frontpgs.tex
r74ec742 r7831e8fb 13 13 \vspace*{1.0cm} 14 14 15 {\Huge\bf High-Performance ConcurrentMemory Allocation}15 {\Huge\bf \CFA Memory Allocation} 16 16 17 17 \vspace*{1.0cm} … … 136 136 137 137 The goal of this thesis is to build a low-latency memory allocator for both kernel and user multi-threaded systems, which is competitive with the best current memory allocators, while extending the feature set of existing and new allocator routines. 138 A new llheap memory-allocator is created that achieves all of these goals, while maintaining and managing sticky allocation properties for zero-fill ed and alignedallocations without a performance loss.138 A new llheap memory-allocator is created that achieves all of these goals, while maintaining and managing sticky allocation properties for zero-fill and alignment allocations without a performance loss. 139 139 Hence, it becomes possible to use @realloc@ frequently as a safe operation, rather than just occasionally, because it preserves sticky properties when enlarging storage requests. 140 140 Furthermore, the ability to query sticky properties and information allows programmers to write safer programs, as it is possible to dynamically match allocation styles from unknown library routines that return allocations. 141 141 The C allocation API is also extended with @resize@, advanced @realloc@, @aalloc@, @amemalign@, and @cmemalign@ so programmers do not make mistakes writing theses useful allocation operations. 142 142 llheap is embedded into the \uC and \CFA runtime systems, both of which have user-level threading. 143 \PAB{The ability to use \CFA's advanced type-system (and possibly \CC's too) to have one allocation routine with advanced memory operations as positional arguments shows how far the allocation API can be pushed, which increases safety and greatly simplifies programmer's use of dynamic allocation.} 143 The ability to use \CFA's advanced type-system (and possibly \CC's too) to have one allocation routine with completely orthogonal sticky properties shows how far the allocation API can be pushed, which increases safety and greatly simplifies programmer's use of dynamic allocation. 144 144 145 145 The llheap allocator also provides comprehensive statistics for all allocation operations, which are invaluable in understanding and debugging a program's dynamic behaviour. 146 No other memory allocator examined in the thesis provides suchcomprehensive statistics gathering.147 As well, llheap provides a debugging mode where allocations are checked with internal pre/post conditions and invariants. Itis extremely useful, especially for students.146 No other memory allocator examined in the thesis provides comprehensive statistics gathering. 147 As well, llheap provides a debugging mode where allocations are checked, along with internal pre/post conditions and invariants, is extremely useful, especially for students. 148 148 While not as powerful as the @valgrind@ interpreter, a large number of allocations mistakes are detected. 149 149 Finally, contention-free statistics gathering and debugging have a low enough cost to be used in production code. 150 150 151 A micro-benchmark test-suite is started for comparing allocators, rather than relying on a suite of arbitrary programs . Ithas been an interesting challenge.151 A micro-benchmark test-suite is started for comparing allocators, rather than relying on a suite of arbitrary programs, has been an interesting challenge. 152 152 These micro-benchmarks have adjustment knobs to simulate allocation patterns hard-coded into arbitrary test programs. 153 Existing memory allocators, glibc, dlmalloc, hoard, jemalloc, ptmalloc3, rpmalloc, tbmalloc ,and the new allocator llheap are all compared using the new micro-benchmark test-suite.153 Existing memory allocators, glibc, dlmalloc, hoard, jemalloc, ptmalloc3, rpmalloc, tbmalloc and the new allocator llheap are all compared using the new micro-benchmark test-suite. 154 154 \cleardoublepage 155 155
Note:
See TracChangeset
for help on using the changeset viewer.