首页 > > 详细

Lab-4: Malloc lab

Home Schedule Lab
Lab-4: Malloc lab
Due: 11/29
Introduction
In this lab you will be writing a dynamic storage allocator for C programs, i.e., your own version
of the malloc , free and realloc routines. You are encouraged to explore the design space
creatively and implement an allocator that is correct, efficient and fast.
This is an individual lab.
Obtaining the lab
$ cd cso-labs
$ git fetch upstream
$ git merge upstream/master
This creates a number of new files in subdirectory malloclab/ .
Change mm.c only
The only file you should modify for this lab is mm.c .
Working on the Lab
In mm.c , you should implement the following five functions (which are declared in mm.h )
Computer Systems Organization
CSCI-UA.0201(005), Fall 2018
int mm_init(void);
void* mm_malloc(size_t size);
void mm_free(void *ptr);
void* mm_realloc(void *ptr, size_t size);
void mm_checkheap(int verbose);
The existing code in mm.c implements the simplest but still functionally correct malloc package
that we could think of. Using this as a starting place, modify these functions (and possibly
define others), so that they obey the following semantics:
mm_init : Before calling mm_malloc mm_realloc or mm_free , the application program (i.e.,
the trace-driven driver program that you will use to evaluate your implementation) calls
mm_init to perform any necessary initializations, such as allocating the initial heap area.
The return value should be -1 if there was a problem in performing the initialization, 0
otherwise.
mm_malloc : The mm_malloc routine returns a pointer to an allocated block payload of at
least size bytes. The entire allocated block should lie within the heap region and should
not overlap with any other allocated chunk.
We will comparing your implementation to the version of malloc supplied in the standard
C library. Since the standard C library malloc always returns payload pointers that are
aligned to 16 bytes, your malloc implementation should do likewise and always return 16-
byte aligned pointers.
mm_free : The mm_free routine frees the block pointed to by ptr. It returns nothing. This
routine is only guaranteed to work when the passed pointer ptr was returned by an earlier
call to mm_malloc or mm_realloc and has not yet been freed.
mm_realloc : The mm_realloc routine returns a pointer to an allocated region of at least
size bytes with the following constraints.
if ptr is NULL, the call is equivalent to mm_malloc(size)
if size is equal to zero, the call is equivalent to mm_free(ptr)} ;
if ptr is not NULL, it must have been returned by an earlier call to mm_malloc or
mm_realloc . The call to mm_realloc changes the size of the memory block pointed
to by ptr (i.e.the old block) to size bytes and returns the address of the new
block. Notice that the address of the new block might be the same as the old block,
or it might be different, depending on your implementation, the amount of internal
fragmentation in the old block, and the size of the realloc request.
The contents of the new block are the same as those of the old ptr block, up to the
minimum of the old and new sizes. Everything else is uninitialized. For example, if
the old block is 8 bytes and the new block is 12 bytes, then the first 8 bytes of the
new block are identical to the first 8 bytes of the old block and the last 4 bytes are
uninitialized. Similarly, if the old block is 8 bytes and the new block is 4 bytes, then
the contents of the new block are identical to the first 4 bytes of the old block.
Lastly, mm_checkheap : The mm_cheapheap routine is an auxilary routine that checks the
consistency of your heap. The function argument int verbose can be used to turn on/off
verbose debug printing.
The malloc,free, realloc semantics match the the semantics of the C standard library's malloc,
realloc, and free routines. Type man malloc for the complete documentation.
When implementing mm_init , mm_free , mm_malloc mm_realloc functions, you need to invoke
the following functions which simulate the the memory system for your dynamic memory
allocator. They are defined in memlib.c :
void *mem_sbrk(int incr) : Expands the heap by incr bytes, where incr is a positive nonzero
integer and returns a generic pointer to the first byte of the newly allocated heap
area. The semantics are identical to the Unix sbrk function, except that mem_sbrk
accepts only a positive non-zero integer argument.
void *mem_heap_lo(void) : Returns a generic pointer to the first byte in the heap.
void *mem_heap_hi(void) : Returns a generic pointer to the last byte in the heap.
size_t mem_heapsize(void) : Returns the current size of the heap in bytes.
size_t mem_pagesize(void) : Returns the system's page size in bytes
Checking Heap Consistency
Dynamic memory allocators are notoriously tricky beasts to program correctly and efficiently.
They are difficult to program correctly because they involve a lot of untyped pointer
manipulation. We ask you to write mm_checkheap to scan the heap and checks it for
consistency.
Some examples of what a heap checker might check are:
Is every block in the free list marked as free?
Are there any contiguous free blocks that somehow escaped coalescing?
Is every free block actually in the free list?
Do the pointers in the free list point to valid free blocks?
Do any allocated blocks overlap?
Do the pointers in a heap block point to valid heap addresses?
Your heap checker will consists of the function void mm_heapcheck(int verbose) , to be
implemented in mm.c . It will check any invariants or consistency conditions you consider
prudent. It returns a nonzero value if and only if your heap is consistent. You are not limited to
the listed suggestions nor are you required to check all of them.
This consistency checker is for your own debugging during development. When you submit
mm.c , make sure to remove any calls to mm_checkheap as they will slow down your throughput.
Style points will be given for your mm_checkheap function.
Testing for correctness and performance
We provide you with a tester program mdriver.c that tests your mm.c for correctness, space
utilization, and throughput.
The tester mdriver reads a set of trace files, each of which contains a sequence of allocate,
reallocate, and free events corresponding to some example application workload. It then calls
your mm_malloc , mm_realloc , and mm_free routines according to the sequence of events.
To run the tester, type:
$ ./mdriver -V
The -V turns on verbose printing in the tester.
To run the tester on one specific tracefile instead of all of the default tracefiles, type:
$./mdriver -V -f tracefile
All the tracefiles can be found in the traces/ subdirectory.
You can type $./mdriver -h to see a full list of command line options.
An example naive implementation
We give you an example naive implementation in mm-naive.c . You may compile it by
typing make . You can test it by typing ./mdriver-naive . It passes all but one trace
due to running out of memory. The naive implementation's performance is pretty bad.
Programming Rules
The only file you should be modifying is mm.c .
You should not invoke any memory-management related library calls or system calls, i.e.
you cannot use malloc, calloc, free, realloc, sbrk, brk or any variants of these calls in your
code. You may use memcpy and other C library functions that are not related to memorymanagement.
In case of doubt, please check with the staff on Piazza.
You should not use any dynamically sized data structures such as dynamically-sized
arrays, trees, or lists in your program. Yes, you can define a global array of a fixed number
of elements of structs, pointers or other scalars.
For consistency with the C standard library's malloc package, which returns blocks
aligned on 16-byte boundaries, your allocator must always return pointers that are aligned
to 16-byte boundaries. The tester will enforce this requirement for you.
Programming Advice
Programming style:
Please avoid using C Macros (like those given in the textbook). Try to define your header
as structs and use regular C helper functions to access your implicit/explict list. See mmnaive.
c as an example for these helper functions.
Your code should have a header comment that describes the overall design of your
malloc implementation: e.g. the organization of the free list. Each function should also
have a header comment that describes what the function does.
Your heap consistency checker mm_checkheap should be thorough.
As is the case with other labs, you will be graded for style and we will deduct up to 20%
of total lab points for bad style based on our subjective evaluation. Please read this style
guide and follow the advice.
Apart from writing code in good style, you should follow these advice:
Use simple workloads first to debug correctness: We provide two very simple trace files
short{1,2}.rep to simplify debugging. Type mdriver -f short1.rep to test your memory
allocator on one of these workloads first.
Use gdb. It will help you isolate and identify out of bounds memory references.
Study the textbook and lecture description of the malloc designs carefully and use one
design (e.g. implicit list) as a starting point. However, I do not recommend you use the
textbook programming style of doing pointer arithmetic everywhere and using C
macros instead of regular functions. It makes the code harder to read and more bugprone.
Define structs to use as your chunk meta-data and use regular helper functions,
as demonstrated in mm-naive.c
Do your implementation in stages. The first 9 traces contain requests to malloc and
free . The last 2 traces contain requests for realloc , malloc , and free . We recommend
that you start by getting your malloc and free routines working correctly and efficiently
on the first 9 traces. Only then should you turn your attention to the realloc
implementation. For starters, build realloc on top of your existing malloc and free
implementations. But to get really good performance, you will need to build a stand-alone
realloc .
For advanced students, you should consider learning to use a profiler, such as gprof , to
understand and optimize the performance of your program.
Evaluation
You will receive zero points if you break any of the rules or your code is buggy and crashes the
tester. Otherwise, your grade will be calculated as follows:
Correctness (20 points). You will receive full points if your solution passes the
correctness tests performed by the tester program. You will receive partial credit for each
correct trace.
Performance (40 points). Two performance metrics will be used to evaluate your
solution:
Space utilization: The peak ratio between the aggregate amount of memory used by
the tester (i.e., allocated via mm_malloc or mm_realloc but not yet freed via
mm_free ) and the size of the heap used by your allocator. The optimal ratio equals
to 1. You should find good policies to minimize fragmentation in order to make this
ratio as close as possible to the optimal.
Throughput: The average number of operations completed per second.
The tester program summarizes the performance of your allocator by computing a
performance index, which is a weighted sum of the space utilization (U) and throughput
(T)
Performance index = 0.6*U + 0.4*min(1, T/T_libc)
where U is your space utilization, T is your throughput, and T_libc is the measured
throughput of Standard C library's malloc on your system on the default traces.
Observing that both memory and CPU cycles are expensive system resources, we adopt
this formula to encourage balanced optimization of both memory utilization and
throughput. Ideally, the performance index will reach 100%. To receive a good score, you
must achieve a balance between utilization and throughput.
Handin Procedure
To handin your files, simply commit and push them to github.com
$ git commit -am "Finish lab4"
$ git push origin
We will fetching your lab files from Github.com at the specified deadline and grade them.

联系我们
  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp
热点标签

联系我们 - QQ: 99515681 微信:codinghelp
程序辅导网!