diff --git a/KernelModule/customMemAlloc.c b/KernelModule/customMemAlloc.c new file mode 100644 index 0000000..8a67d90 --- /dev/null +++ b/KernelModule/customMemAlloc.c @@ -0,0 +1,471 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +// added to print uint +// 64 +// #include + +struct contigmem_buffer { + void *addr; + int refcnt; + struct mtx mtx; +}; + +struct contigmem_vm_handle { + int buffer_index; +}; + +static int contigmem_load(void); +static int contigmem_unload(void); +static int contigmem_physaddr(SYSCTL_HANDLER_ARGS); + +static d_mmap_single_t contigmem_mmap_single; +static d_open_t contigmem_open; +static d_close_t contigmem_close; + +static int contigmem_num_buffers = RTE_CONTIGMEM_DEFAULT_NUM_BUFS; +static int64_t contigmem_buffer_size = RTE_CONTIGMEM_DEFAULT_BUF_SIZE; + +static eventhandler_tag contigmem_eh_tag; +static struct contigmem_buffer contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; +static struct cdev *contigmem_cdev = NULL; +static int contigmem_refcnt; + +TUNABLE_INT("hw.contigmem.num_buffers", &contigmem_num_buffers); +TUNABLE_QUAD("hw.contigmem.buffer_size", &contigmem_buffer_size); + +static SYSCTL_NODE(_hw, OID_AUTO, contigmem, CTLFLAG_RD, 0, "contigmem"); + +SYSCTL_INT(_hw_contigmem, OID_AUTO, num_buffers, CTLFLAG_RD, + &contigmem_num_buffers, 0, "Number of contigmem buffers allocated"); +SYSCTL_QUAD(_hw_contigmem, OID_AUTO, buffer_size, CTLFLAG_RD, + &contigmem_buffer_size, 0, "Size of each contiguous buffer"); +SYSCTL_INT(_hw_contigmem, OID_AUTO, num_references, CTLFLAG_RD, + &contigmem_refcnt, 0, "Number of references to contigmem"); + +static SYSCTL_NODE(_hw_contigmem, OID_AUTO, physaddr, CTLFLAG_RD, 0, + "physaddr"); + +MALLOC_DEFINE(M_CONTIGMEM, "customcontigmem", "customcontigmem(4) allocations"); + + +/* + * The offset in sysent where the syscall is allocated. + */ +static int offset = NO_SYSCALL; + +static int contigmem_modevent(module_t mod, int type, void *arg) +{ + int error = 0; + + switch (type) { + case MOD_LOAD: + error = contigmem_load(); + break; + case MOD_UNLOAD: + error = contigmem_unload(); + break; + default: + break; + } + + return error; +} + +moduledata_t contigmem_mod = { + "contigmem", + (modeventhand_t)contigmem_modevent, + 0 +}; + +DECLARE_MODULE(contigmem, contigmem_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); +MODULE_VERSION(contigmem, 1); + +static struct cdevsw contigmem_ops = { + .d_name = "contigmem", + .d_version = D_VERSION, + .d_flags = D_TRACKCLOSE, + .d_mmap_single = contigmem_mmap_single, + .d_open = contigmem_open, + .d_close = contigmem_close, +}; + +static int +contigmem_load() +{ + + // get page size + printf("%d FreeBSD page size \n",PAGE_SIZE); + + char index_string[8], description[32]; + int i, error = 0; + void *addr; + + if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { + printf("%d buffers requested is greater than %d allowed\n", + contigmem_num_buffers, RTE_CONTIGMEM_MAX_NUM_BUFS); + error = EINVAL; + goto error; + } + + if (contigmem_buffer_size < PAGE_SIZE || + (contigmem_buffer_size & (contigmem_buffer_size - 1)) != 0) { + printf("buffer size 0x%lx is not greater than PAGE_SIZE and " + "power of two\n", contigmem_buffer_size); + error = EINVAL; + goto error; + } + + for (i = 0; i < contigmem_num_buffers; i++) { + addr = contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, + 0, BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); + if (addr == NULL) { + printf("contigmalloc failed for buffer %d\n", i); + error = ENOMEM; + goto error; + } + +#ifndef RTE_ARCH_ARM_PURECAP_HACK + printf("%2u: virt=%p phys=%p\n", i, addr, + (void *)pmap_kextract((vm_offset_t)addr)); +#endif + + mtx_init(&contigmem_buffers[i].mtx, "contigmem", NULL, MTX_DEF); + contigmem_buffers[i].addr = addr; + contigmem_buffers[i].refcnt = 0; + + snprintf(index_string, sizeof(index_string), "%d", i); + snprintf(description, sizeof(description), + "phys addr for buffer %d", i); + SYSCTL_ADD_PROC(NULL, + &SYSCTL_NODE_CHILDREN(_hw_contigmem, physaddr), OID_AUTO, + index_string, CTLTYPE_U64 | CTLFLAG_RD, + (void *)(uintptr_t)i, 0, contigmem_physaddr, "LU", + description); + } + + contigmem_cdev = make_dev_credf(0, &contigmem_ops, 0, NULL, UID_ROOT, + GID_WHEEL, 0600, "contigmem"); + + return 0; + +error: + for (i = 0; i < contigmem_num_buffers; i++) { + if (contigmem_buffers[i].addr != NULL) { + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); + contigmem_buffers[i].addr = NULL; + } + if (mtx_initialized(&contigmem_buffers[i].mtx)) + mtx_destroy(&contigmem_buffers[i].mtx); + } + + return error; + +// Want to design contig load to do nothing +} + +static int +contigmem_unload() +{ + int i; + + if (contigmem_refcnt > 0) + return EBUSY; + + if (contigmem_cdev != NULL) + destroy_dev(contigmem_cdev); + + if (contigmem_eh_tag != NULL) + EVENTHANDLER_DEREGISTER(process_exit, contigmem_eh_tag); + + for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) { + if (contigmem_buffers[i].addr != NULL) + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); + if (mtx_initialized(&contigmem_buffers[i].mtx)) + mtx_destroy(&contigmem_buffers[i].mtx); + } + + return 0; +} + +static int +contigmem_physaddr(SYSCTL_HANDLER_ARGS) +{ + uint64_t physaddr; + int index = (int)(uintptr_t)arg1; + + physaddr = (uint64_t)vtophys(contigmem_buffers[index].addr); + return sysctl_handle_64(oidp, &physaddr, 0, req); +} + +static int +contigmem_open(struct cdev *cdev, int fflags, int devtype, + struct thread *td) +{ + + printf("Contigmem opened \n"); + + atomic_add_int(&contigmem_refcnt, 1); + + return 0; +} + +static int +contigmem_close(struct cdev *cdev, int fflags, int devtype, + struct thread *td) +{ + + atomic_subtract_int(&contigmem_refcnt, 1); + + return 0; +} + +static int +contigmem_cdev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred, u_short *color) +{ + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + atomic_add_int(&contigmem_refcnt, 1); + + mtx_lock(&buf->mtx); + if (buf->refcnt == 0) + memset(buf->addr, 0, contigmem_buffer_size); + buf->refcnt++; + mtx_unlock(&buf->mtx); + + return 0; +} + +static void +contigmem_cdev_pager_dtor(void *handle) +{ + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + mtx_lock(&buf->mtx); + buf->refcnt--; + mtx_unlock(&buf->mtx); + + free(vmh, M_CONTIGMEM); + + atomic_subtract_int(&contigmem_refcnt, 1); +} + +static int +contigmem_cdev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, + vm_page_t *mres) +{ + vm_paddr_t paddr; + vm_page_t m_paddr, page; + vm_memattr_t memattr, memattr1; + + memattr = object->memattr; + + VM_OBJECT_WUNLOCK(object); + + paddr = offset; + + m_paddr = vm_phys_paddr_to_vm_page(paddr); + if (m_paddr != NULL) { + memattr1 = pmap_page_get_memattr(m_paddr); + if (memattr1 != memattr) + memattr = memattr1; + } + + if (((*mres)->flags & PG_FICTITIOUS) != 0) { + /* + * If the passed in result page is a fake page, update it with + * the new physical address. + */ + page = *mres; + VM_OBJECT_WLOCK(object); + vm_page_updatefake(page, paddr, memattr); + } else { + /* + * Replace the passed in reqpage page with our own fake page and + * free up the original page. + */ + page = vm_page_getfake(paddr, memattr); + VM_OBJECT_WLOCK(object); +#if __FreeBSD__ >= 13 + vm_page_replace(page, object, (*mres)->pindex, *mres); +#else + vm_page_t mret = vm_page_replace(page, object, (*mres)->pindex); + KASSERT(mret == *mres, + ("invalid page replacement, old=%p, ret=%p", *mres, mret)); + vm_page_lock(mret); + vm_page_free(mret); + vm_page_unlock(mret); +#endif + *mres = page; + } + + page->valid = VM_PAGE_BITS_ALL; + + return VM_PAGER_OK; +} + +static struct cdev_pager_ops contigmem_cdev_pager_ops = { + .cdev_pg_ctor = contigmem_cdev_pager_ctor, + .cdev_pg_dtor = contigmem_cdev_pager_dtor, + .cdev_pg_fault = contigmem_cdev_pager_fault, +}; + +static int +contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, + struct vm_object **obj, int nprot) +{ + + // Testing if this is called when file is opened + printf("contigmem_mmap_single called \n"); + + struct contigmem_vm_handle *vmh; + uint64_t buffer_index; + + /* + * The buffer index is encoded in the offset. Divide the offset by + * PAGE_SIZE to get the index of the buffer requested by the user + * app. + */ + buffer_index = *offset / PAGE_SIZE; + if (buffer_index >= contigmem_num_buffers) + return EINVAL; + + if (size > contigmem_buffer_size) + return EINVAL; + + vmh = malloc(sizeof(*vmh), M_CONTIGMEM, M_NOWAIT | M_ZERO); + if (vmh == NULL) + return ENOMEM; + vmh->buffer_index = buffer_index; + + *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index].addr); + *obj = cdev_pager_allocate(vmh, OBJT_DEVICE, &contigmem_cdev_pager_ops, + size, nprot, *offset, curthread->td_ucred); + + return 0; +} + + +// SAMPLE SYSCALL IMPLEMENTATION +// /*- +// * SPDX-License-Identifier: BSD-2-Clause +// * +// * Copyright (c) 1999 Assar Westerlund +// * All rights reserved. +// * +// * Redistribution and use in source and binary forms, with or without +// * modification, are permitted provided that the following conditions +// * are met: +// * 1. Redistributions of source code must retain the above copyright +// * notice, this list of conditions and the following disclaimer. +// * 2. Redistributions in binary form must reproduce the above copyright +// * notice, this list of conditions and the following disclaimer in the +// * documentation and/or other materials provided with the distribution. +// * +// * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +// * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +// * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +// * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +// * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +// * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +// * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +// * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// * SUCH DAMAGE. +// */ + +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// /* +// * The function for implementing the syscall. +// */ +// static int +// hello(struct thread *td, void *arg) +// { + +// printf("hello kernel\n"); +// return (0); +// } + +// /* +// * The `sysent' for the new syscall +// */ +// static struct sysent hello_sysent = { +// .sy_narg = 0, +// .sy_call = hello +// }; + +// /* +// * The offset in sysent where the syscall is allocated. +// */ +// static int offset = NO_SYSCALL; + +// /* +// * The function called at load/unload. +// */ +// static int +// load(struct module *module, int cmd, void *arg) +// { +// int error = 0; + +// switch (cmd) { +// case MOD_LOAD : +// printf("syscall loaded at %d\n", offset); +// break; +// case MOD_UNLOAD : +// printf("syscall unloaded from %d\n", offset); +// break; +// default : +// error = EOPNOTSUPP; +// break; +// } +// return (error); +// } + +// SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL); \ No newline at end of file diff --git a/docs/evaluation/#evaluation-plan.org# b/docs/evaluation/#evaluation-plan.org# index c5a5767..0695114 100644 --- a/docs/evaluation/#evaluation-plan.org# +++ b/docs/evaluation/#evaluation-plan.org# @@ -8,8 +8,8 @@ This will consist of a paragraph of the following structure: ** Expirement setup - Mentions about the CHERI board used. - specs of the board -- mentions about the compiled flag called benchmark ABI.(https://ctsrd-cheri.github.io/morello-early-performance-results/performance-methodology/abis-code-generation-and-compilation.html) -- mentions how the various benchmark are compared and breifly +- mentions about the compiled flag called benchmark ABI. +- mentions how the various bechmark are compared and breifly mentions about the ARM performance counters. ** Performance counters used @@ -20,7 +20,8 @@ This will consist of a paragraph of the following structure: This is more in a bulletin point manner. ** Graphs listed -- Talks about each of the benchmark patterns indenpendently (Bulletin points elaborated). +- Talks about each of the benchmark patterns indenpendently + (Bulletin points elaborated). - Builds up on those with multiple runs. ** Usability: @@ -28,4 +29,4 @@ Talk about the ease of running the new allocator. - Limitaion why certain benchmarks did not work. - The eager Huge page design while designed for fragmentation can still incur fragmentation at a user level. -- How was the memory allocator swapped. +- How was the memory allocator swapped. \ No newline at end of file diff --git a/docs/evaluation/evaluation-plan.org b/docs/evaluation/evaluation-plan.org index 7fb1131..a15f43e 100644 --- a/docs/evaluation/evaluation-plan.org +++ b/docs/evaluation/evaluation-plan.org @@ -20,7 +20,8 @@ This will consist of a paragraph of the following structure: This is more in a bulletin point manner. ** Graphs listed -- Talks about each of the benchmark patterns indenpendently (Bulletin points elaborated). +- Talks about each of the benchmark patterns indenpendently + (Bulletin points elaborated). - Builds up on those with multiple runs. ** Usability: diff --git a/docs/evaluation/evaluation.html b/docs/evaluation/evaluation.html new file mode 100644 index 0000000..c8a446e --- /dev/null +++ b/docs/evaluation/evaluation.html @@ -0,0 +1,482 @@ + + + + + + + + + + + + + +
+ +
+

1. Evaluation

+
+

+We conducted tests of the FAT Pointer-based range addresses against Jemalloc, +the default memory allocator for CHERIBSD(, ), to assess the performance improvements +enabled by a CHERI-based huge page-aware allocator. Specifically, we evaluated +the reduction in TLB misses and its impact on overall +performance metrics, such as wall clock runtime. +

+ +

+To comprehensively analyze the proposed allocator, we categorized benchmarks into +two classes which are micro and macro benchmarks. Micro benchmarks comprise smaller +C programs designed to target specific allocator patterns, enabling us to evaluate +detailed aspects of the allocator's behavior. Macro benchmarks, on the other hand, +encompass larger, real-world C programs, allowing us to assess the allocator's +performance in more practical, real-world scenarios. +

+ +

+The experiment setup details the software stack used for evaluation. It includes +the specific configurations, compiler options, and system environment tailored +to benchmark the proposed allocator. This ensures consistency and repeatability +in our results, providing a solid foundation for meaningful comparisons. +

+ +

+We further elaborated on the two classes of benchmarks executed. Micro benchmarks +focused on particular allocation and deallocation patterns, such as sequential and +random memory accesses, to stress-test the allocator under controlled conditions. +Macro benchmarks involved real-world applications, offering insights into how +the allocator performs with complex memory allocation demands, large datasets, +and varying execution contexts. +

+ +

+The results section presents the outcomes of our benchmarks, highlighting key metrics +such as TLB miss rates, memory usage, and runtime performance. We observed that the +proposed allocator demonstrated significant improvements in reducing TLB misses, +leading to noticeable enhancements in runtime efficiency for both micro and macro +benchmarks. The behavior of specific allocation patterns and their impact on memory +performance is detailed, providing a nuanced understanding of the allocator's effectiveness. +

+ +

+Based on the evaluated results, the usability of the proposed allocator shows promise +for applications requiring optimized memory management and reduced overhead from TLB misses. +However, limitations were also identified, such as scenarios where the allocator's performance +gains were marginal or where it introduced additional complexity in memory management. These +limitations provide a roadmap for future optimizations and refinements of the allocator design. +

+
+ +
+

1.1. Expirement setup

+
+

+The CHERI Morello board was used to evaluate the proposed memory allocator. +Morello implements the ARM A76 with enhanced server-class memory, featuring a +quad-core ARM CPU with capability extensions. The L1 and L2 caches were modified +to proliferate the capability bit, ensuring compatibility with CHERI's capability-based +memory model. When compiling the C programs for benchmarking, the Benchmark ABI was +used as recommended by the CHERI community. This compilation mode was enabled using +the Clang compiler. +

+ +

+The Benchmark ABI was specifically designed because the Morello branch predictor +was not expanded to predict bounds. Consequently, a capability-based jump introduces +stalls in later PCC-dependent instructions until bounds are established. This issue +is particularly significant during dynamically linked calls and returns between +libraries, where bounds are changed to cover the called or returned-to library. +Such stalls can negatively affect performance, making the Benchmark ABI an essential +consideration for this evaluation. +

+ +

+Each C program was executed using two different memory allocators. The first was +the modified C allocator, imported as a header file. This approach was necessary +because the Benchmark ABI shared object file exhibited unexpected behavior, +failing to overwrite the C program at runtime with the intended malloc functions. +The second allocator was the standard OS memory allocator, which, in the case of +CHERIBSD, is Jemalloc. +

+ +

+Performance measurements were carried out using ARM performance counters to +ensure accurate evaluation. These counters provided detailed metrics, allowing +us to compare the performance of the two allocators and assess the impact of +the proposed changes. +

+
+ +
+

1.1.1. Performance counters used

+
+ + + + + + + + + + +
+  Performance counter                               + +  Description                                 +
+  Wall clock                                       
+                                                   
+                                                   
+  (p/l1d_tlb_rd) L1 data TLB reads                 
+                                                   
+  (p/l2d_tlb_rd) L2 data TLB reads                 
+                                                   
+  (p/l1d_tlb_refill) L1 data TLB refills           
+                                                   
+                                                   
+                                                   
+                                                   
+                                                   
+                                                   
+                                                   
+                                                   
+                                                   
+  (p/cpu_cycles) CPU cycles                        
+                                                   
+                                                   
+                                                   
+                                                   
+                                                   
+                                                   
+  (p/dtlb_walk) Data TLB walks                     
+                                                   
+                                                   
+  (p/ll_cache_miss_rd) Last level cache miss reads 
+                                                   
+                                                   
+                                                    +
+  The actual time taken from the start of a  
+  computer program to the end.               
+                                             
+  Level 1 data TLB access, read              
+                                             
+  Level 2 data TLB access, read              
+                                             
+  Level 1 data TLB refill.                   
+  The Level 1 data TLB refill                
+  counter tracks each access to              
+  the L1D_TLB that results                   
+  in a refill of the Level 1 data            
+  or unified TLB. This includes any          
+  access that requires a memory lookup       
+  due to a translation table walk            
+  or accessing another level of TLB cache.   
+                                             
+  The CPU CYCLES counter increases with      
+  every clock cycle. However, it can be      
+  affected by changes in clock frequency,    
+  such as when WFI (Wait for Interrupt)      
+  or WFE (Wait for Event)                    
+  instructions pause the clock.              
+                                             
+  Data TLB access with at least              
+  one translation table walk.                
+                                             
+  Last level cache miss, read                
+  (This refers to every miss in the          
+  Last level cache that occurs               
+  during a memory read operation.)            +
+
+
+ +
+

1.1.2. Benchmarks

+
+

+The benchmarks are classified into 2 classes: +

+
+ +
    +
  1. Micro benchmark
    +
    +
      +
    • GLIBC: The Glibc benchmark evaluates the performance of +malloc and free functions in single-threaded, multi-threaded, +and emulated multi-threading scenarios using various block sizes and +allocation patterns. It simulates real-world memory usage by partially +deallocating blocks in FIFO order and fully deallocating them in LIFO order. +Results are gathered across configurations to analyze performance variations.
    • +
    • MemAccess: This benchmark by Alex Bordei evaluates the performance impact of +memory access patterns by constructing and traversing a doubly +linked list with varying working set sizes. It supports sequential or +randomized structures, optional node operations, and multithreaded +traversal using pthreads. The program dynamically allocates memory and systematically +doubles the working set size to analyze memory hierarchy behavior.
    • +
    +
    +
  2. + +
  3. Macro runs
    +
    +
      +
    • Kmeans: Kmeans implements a parallelized K-means clustering algorithm that +assigns data points to clusters based on proximity to centroids, +iteratively updating them until convergence. The computation is +distributed across threads using the pthread library, dynamically +assigning tasks to optimize performance. Parameters like data size +and clusters are configurable, and the program ensures efficient +memory management and synchronization.
    • +
    • Richards: Richards is a task scheduling benchmark that simulates a +multitasking environment with tasks of varying types and priorities, +communicating through queued packets. The schedule function manages +task execution based on state and priority, tracking processed packets +and held tasks for performance evaluation. Configurable iterations and +timing help measure system performance and ensure correctness.
    • +
    +
    +
  4. +
+
+
+ +
+

1.2. Results

+
+ +
+

allbenchmarks.png +

+
+ + +
+

kmeans.png +

+
+ + +
+

glibc.png +

+
+
+
+ +
+

1.3. Usability

+
+
+
+
+

Author: Akilan

+

Created: 2025-01-12 Sun 17:26

+

Validate

+
+ + \ No newline at end of file diff --git a/docs/evaluation/evaluation.org b/docs/evaluation/evaluation.org index a34d6c2..724f72c 100644 --- a/docs/evaluation/evaluation.org +++ b/docs/evaluation/evaluation.org @@ -196,12 +196,113 @@ The benchmarks are classified into 2 classes: #+ATTR_ORG: :align center [[./diagrams/allbenchmarks.png]] +#+BEGIN_COMMENT +The graph above refers to the precentage difference between the modified +memory allocator against the default system memory allocator which is +Jemalloc. Since FAT pointer memory allocator is desgined to allocate +with huge pages the results in graph above has the appripirate +expected corresponding behavoir. It is noticable the data +TLB walk, L2 data TLB reads and refill are consistently +90% lesser than the default memory allocator accross +the benchmarks listed on the graph above. This is +because of a single huge page entry at the l1 TLB +layer. This means most address translations hit L1 +TLB without having to walk through the heirarchy of +TLB translations. + +The micro benchmarks are designed for more memory reads +and shows on average a 50% reduction on wallclock runtimes. +The macro benchmarks on the other hand which are larger +classes of C programs have minimal differences in wall +clock run times. +#+END_COMMENT + + +The graph above highlights the performance comparison between the modified memory allocator and +Jemalloc, the default memory allocator. The FAT pointer memory allocator, specifically optimized +for use with huge pages, demonstrates a clear advantage in scenarios where memory allocation +patterns benefit from its design. The results align with expectations, showcasing the impact +of its capability to handle memory more efficiently by leveraging huge pages. + +A particularly striking observation is the significant reduction in data TLB walks, +L2 data TLB reads, and TLB refills—consistently showing a 90% decrease across all +benchmarks compared to Jemalloc. This improvement is due to the modified allocator's +use of a single huge page entry at the L1 TLB layer. By enabling most address translations +to be resolved directly at the L1 TLB, the need to walk through the deeper TLB hierarchy is +largely eliminated. This reduction in translation overhead is a key factor in the allocator's +superior performance for certain types of workloads. + +The micro benchmarks, which are crafted to emphasize memory read operations, highlight the +allocator's strengths. These tests simulate frequent and intensive memory access patterns, +where the reduction in TLB misses directly translates into measurable performance gains. +On average, the FAT pointer allocator achieves a 50% reduction in wall clock runtimes for +these workloads, underscoring its ability to optimize high-throughput memory operations. + +On the other hand, macro benchmarks, which represent larger and more complex real-world applications, +exhibit minimal differences in wall clock runtimes when using the FAT pointer allocator. +This outcome is expected, as macro benchmarks typically involve a broader range of operations +beyond memory allocation, diluting the impact of the allocator's optimizations. Additionally, +the benefits of huge pages may be less pronounced for these workloads, as they are often +bottlenecked by factors such as computation or I/O rather than memory translation overhead. + #+ATTR_HTML: :align right #+ATTR_ORG: :align center [[./diagrams/kmeans.png]] +#+BEGIN_COMMENT +The kmeans was executed with various cluster sizes to see +the percentage difference against the baseline allocator as +the size of the workload increases. It can be noted that +the percentage difference stays the same except during +the cluster size of 2000. +#+END_COMMENT +The K-means algorithm was executed with varying cluster sizes to evaluate the performance difference +between the FAT pointer allocator and the baseline allocator as the workload scales. This analysis +aimed to understand how the allocator's optimizations, particularly its ability to manage memory +more efficiently with huge pages, impact performance under different workload conditions. + +For most cluster sizes tested, the percentage difference in performance remained relatively +consistent. This indicates that the allocator's efficiency scales predictably with increasing +workload sizes, suggesting a stable and uniform benefit across different configurations. The +consistent performance gain is likely due to the allocator's ability to minimize TLB misses +and efficiently manage memory allocations for the centroid and data point structures used in +the K-means algorithm. + +However, an anomaly was observed at a cluster size of 2000, where the percentage difference +deviated significantly from the trend. This irregularity could be attributed to several factors. +At this cluster size, the memory access patterns and allocation behavior may align in a way that +temporarily offsets the advantages of the FAT pointer allocator. For example, the memory layout +might interact with system-level caching mechanisms or TLB behavior differently, leading to an +unexpected change in performance. Additionally, the increased complexity of managing a higher +number of clusters might introduce computational overhead that overshadows the memory allocator's +optimizations. + +This observation highlights the importance of testing across a range of workload sizes and +configurations to uncover edge cases or specific scenarios where performance deviates from the +expected pattern. Understanding these anomalies can provide insights into the allocator's +behavior and guide future improvements to address such outliers. Despite the deviation at a +cluster size of 2000, the overall results reaffirm the allocator's capability to maintain +consistent performance benefits across most scenarios. + +#+BEGIN_COMMENT #+ATTR_HTML: :align right #+ATTR_ORG: :align center [[./diagrams/glibc.png]] - +#+END_COMMENT ** Usability +The FAT pointer memory allocator demonstrates significant potential for enhancing +memory management in systems that benefit from huge page optimizations. Its design +effectively reduces TLB misses, achieving up to 90% fewer data TLB walks, L2 TLB reads, +and TLB refills compared to Jemalloc. These improvements lead to noticeable performance +gains, especially in micro benchmarks, where the allocator reduces wall clock runtimes +by an average of 50%. + +The allocator integrates seamlessly into memory-intensive workloads, as evidenced by its +consistent performance across varying cluster sizes in the K-means benchmark, with only +minor anomalies observed under specific conditions. These outliers provide valuable +insights into the allocator's interaction with system-level caching and memory translation mechanisms. + +While the allocator excels in scenarios emphasizing high memory throughput, its impact on +macro benchmarks is less pronounced. This suggests that its benefits are most relevant for +applications with frequent and intensive memory operations rather than those constrained by +computation or I/O bottlenecks. \ No newline at end of file diff --git a/docs/evaluation/evaluation.pdf b/docs/evaluation/evaluation.pdf index cecc05d..93ec0eb 100644 Binary files a/docs/evaluation/evaluation.pdf and b/docs/evaluation/evaluation.pdf differ diff --git a/docs/evaluation/evaluation.tex b/docs/evaluation/evaluation.tex index fa5b979..9599e67 100644 --- a/docs/evaluation/evaluation.tex +++ b/docs/evaluation/evaluation.tex @@ -1,4 +1,4 @@ -% Created 2025-01-09 Thu 22:53 +% Created 2025-01-14 Tue 14:03 % Intended LaTeX compiler: pdflatex \documentclass[11pt]{article} \usepackage[utf8]{inputenc} @@ -27,7 +27,7 @@ \tableofcontents \section{Evaluation} -\label{sec:org02aba25} +\label{sec:orgbbe52ec} We conducted tests of the FAT Pointer-based range addresses against Jemalloc, the default memory allocator for CHERIBSD(, ), to assess the performance improvements @@ -68,7 +68,7 @@ gains were marginal or where it introduced additional complexity in memory manag limitations provide a roadmap for future optimizations and refinements of the allocator design. \subsection{Expirement setup} -\label{sec:org9bf5b27} +\label{sec:org0672379} The CHERI Morello board was used to evaluate the proposed memory allocator. Morello implements the ARM A76 with enhanced server-class memory, featuring a @@ -99,7 +99,7 @@ us to compare the performance of the two allocators and assess the impact of the proposed changes. \subsubsection{Performance counters used} -\label{sec:org294979c} +\label{sec:org9f2d2f7} \begin{center} \begin{tabular}{|l|l|} @@ -142,12 +142,12 @@ Wall clock & The actual time taken from the start of a \\ \end{center} \subsubsection{Benchmarks} -\label{sec:orgddacffd} +\label{sec:org91388b2} The benchmarks are classified into 2 classes: \begin{enumerate} \item Micro benchmark -\label{sec:orgb329a4e} +\label{sec:orgf10bbbd} \begin{itemize} \item GLIBC: The Glibc benchmark evaluates the performance of malloc and free functions in single-threaded, multi-threaded, @@ -164,7 +164,7 @@ doubles the working set size to analyze memory hierarchy behavior. \end{itemize} \item Macro runs -\label{sec:orga786fd0} +\label{sec:orgc073fbd} \begin{itemize} \item Kmeans: Kmeans implements a parallelized K-means clustering algorithm that assigns data points to clusters based on proximity to centroids, @@ -183,19 +183,86 @@ timing help measure system performance and ensure correctness. \end{enumerate} \subsection{Results} -\label{sec:org4bdc0d9} +\label{sec:org306bf15} \begin{center} \includegraphics[width=.9\linewidth]{./diagrams/allbenchmarks.png} \end{center} + +The graph above highlights the performance comparison between the modified memory allocator and +Jemalloc, the default memory allocator. The FAT pointer memory allocator, specifically optimized +for use with huge pages, demonstrates a clear advantage in scenarios where memory allocation +patterns benefit from its design. The results align with expectations, showcasing the impact +of its capability to handle memory more efficiently by leveraging huge pages. + +A particularly striking observation is the significant reduction in data TLB walks, +L2 data TLB reads, and TLB refills—consistently showing a 90\% decrease across all +benchmarks compared to Jemalloc. This improvement is due to the modified allocator's +use of a single huge page entry at the L1 TLB layer. By enabling most address translations +to be resolved directly at the L1 TLB, the need to walk through the deeper TLB hierarchy is +largely eliminated. This reduction in translation overhead is a key factor in the allocator's +superior performance for certain types of workloads. + +The micro benchmarks, which are crafted to emphasize memory read operations, highlight the +allocator's strengths. These tests simulate frequent and intensive memory access patterns, +where the reduction in TLB misses directly translates into measurable performance gains. +On average, the FAT pointer allocator achieves a 50\% reduction in wall clock runtimes for +these workloads, underscoring its ability to optimize high-throughput memory operations. + +On the other hand, macro benchmarks, which represent larger and more complex real-world applications, +exhibit minimal differences in wall clock runtimes when using the FAT pointer allocator. +This outcome is expected, as macro benchmarks typically involve a broader range of operations +beyond memory allocation, diluting the impact of the allocator's optimizations. Additionally, +the benefits of huge pages may be less pronounced for these workloads, as they are often +bottlenecked by factors such as computation or I/O rather than memory translation overhead. + \begin{center} \includegraphics[width=.9\linewidth]{./diagrams/kmeans.png} \end{center} -\begin{center} -\includegraphics[width=.9\linewidth]{./diagrams/glibc.png} -\end{center} +The K-means algorithm was executed with varying cluster sizes to evaluate the performance difference +between the FAT pointer allocator and the baseline allocator as the workload scales. This analysis +aimed to understand how the allocator's optimizations, particularly its ability to manage memory +more efficiently with huge pages, impact performance under different workload conditions. +For most cluster sizes tested, the percentage difference in performance remained relatively +consistent. This indicates that the allocator's efficiency scales predictably with increasing +workload sizes, suggesting a stable and uniform benefit across different configurations. The +consistent performance gain is likely due to the allocator's ability to minimize TLB misses +and efficiently manage memory allocations for the centroid and data point structures used in +the K-means algorithm. + +However, an anomaly was observed at a cluster size of 2000, where the percentage difference +deviated significantly from the trend. This irregularity could be attributed to several factors. +At this cluster size, the memory access patterns and allocation behavior may align in a way that +temporarily offsets the advantages of the FAT pointer allocator. For example, the memory layout +might interact with system-level caching mechanisms or TLB behavior differently, leading to an +unexpected change in performance. Additionally, the increased complexity of managing a higher +number of clusters might introduce computational overhead that overshadows the memory allocator's +optimizations. + +This observation highlights the importance of testing across a range of workload sizes and +configurations to uncover edge cases or specific scenarios where performance deviates from the +expected pattern. Understanding these anomalies can provide insights into the allocator's +behavior and guide future improvements to address such outliers. Despite the deviation at a +cluster size of 2000, the overall results reaffirm the allocator's capability to maintain +consistent performance benefits across most scenarios. \subsection{Usability} -\label{sec:org3b91bbd} +\label{sec:orgb4de289} +The FAT pointer memory allocator demonstrates significant potential for enhancing +memory management in systems that benefit from huge page optimizations. Its design +effectively reduces TLB misses, achieving up to 90\% fewer data TLB walks, L2 TLB reads, +and TLB refills compared to Jemalloc. These improvements lead to noticeable performance +gains, especially in micro benchmarks, where the allocator reduces wall clock runtimes +by an average of 50\%. + +The allocator integrates seamlessly into memory-intensive workloads, as evidenced by its +consistent performance across varying cluster sizes in the K-means benchmark, with only +minor anomalies observed under specific conditions. These outliers provide valuable +insights into the allocator's interaction with system-level caching and memory translation mechanisms. + +While the allocator excels in scenarios emphasizing high memory throughput, its impact on +macro benchmarks is less pronounced. This suggests that its benefits are most relevant for +applications with frequent and intensive memory operations rather than those constrained by +computation or I/O bottlenecks. \end{document} \ No newline at end of file