Created
August 11, 2009 16:14
-
-
Save abyrd/165929 to your computer and use it in GitHub Desktop.
Proof of concept for mmapping Graph structures
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#include <string.h> | |
// 2MiB, the address that mmap always gives me automatically on OSX | |
#define OSX_BASE (void*) 0x00200000 | |
// 16MiB, the address that mmap gives me for bigger mmaps on OSX | |
#define OSX_BASE_BIG (void*) 0x01000000 | |
// upper limit of a 32 bit address space | |
#define MAX_ADDR (void*) 0xFFFFFFFF | |
int main () { | |
size_t chunk_size = 1024 * 1024 * 500; | |
char *map; | |
int i, j, n, status; | |
int map_fd; | |
char pattern = 'A'; | |
void *addr_req; | |
// if I step by < 4kiBytes, i always get the net highest 4096 byte-aligned address | |
for (addr_req = (void*) OSX_BASE_BIG; | |
addr_req < MAX_ADDR; | |
addr_req += (0x1000 + chunk_size) ) { | |
// addr_req += chunk_size) { | |
// using truncate flag here will screw things up | |
map_fd = open("test.mmap", O_CREAT | O_RDWR , 0664); | |
// write( mapno , junk , chunk_size ) ; | |
printf("file number : %d\n", map_fd); | |
// if ( mapno < 0 ) exit( 1 ) ; | |
// for ( n = 0 ; n < chunk_size ; ++ n ) | |
// write( mapno , junk , chunk_size ) ; | |
// resize the file to the size of the memory map | |
// in case it's too small. new part is full of 0s. | |
status = ftruncate( map_fd , chunk_size ); | |
// p = malloc(chunk_size); | |
// p = mmap( (void*)0x00200000, chunk_size, PROT_READ|PROT_WRITE, | |
// MAP_FIXED, mapno, 0); | |
// MAP_PRIVATE seems to run slower, MAP_FIXED fails every time. (too bad) | |
// I think they want to discourage FIXED. | |
map = mmap( addr_req, chunk_size, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0); | |
if ( map == MAP_FAILED ) { printf( "Map failed." ); exit( 2 ); } | |
printf("%d : req 0x%08x \n%d : map 0x%08x\n", i, addr_req, i, map); | |
// check a g->mmapped flag in add_vertex | |
// or a v->owner->mmapped | |
// graph should be declared mmapped at creation | |
status = 0; | |
for (j = 0; j < chunk_size; j++) { | |
if ( map[j] != pattern ) status = -1; | |
break; | |
} | |
// will differ if file was not yet created | |
// should be identical after iteration 1 | |
if (status) printf( "Contents differed.\n" ); | |
else printf( "Contents identical.\n"); | |
pattern++; | |
memset(map, pattern, chunk_size); | |
//msync(mapno); | |
munmap(map, chunk_size); | |
close(map_fd); | |
//free(p); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/types.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#include <string.h> | |
#define malloc mmmalloc | |
#define free mmfree | |
// 2MiB, the address that mmap always gives me automatically on OSX | |
#define OSX_BASE (void*) 0x00200000 | |
// 16MiB, the address that mmap gives me for bigger mmaps on OSX | |
#define OSX_BASE_BIG (void*) 0x01000000 | |
// upper limit of a 32 bit address space | |
#define MAX_ADDR (void*) 0xFFFFFFFF | |
// 1MiB a small dynamic memory area | |
#define ALLOC_SPACE 0x00FFFFFF | |
// 4KiB is the page size | |
#define ALLOC_CHUNK 0x0000FFFF | |
static void * alloc_base = NULL; | |
static void * alloc_top = NULL; | |
static int alloc_fd; | |
static int alloc_mmap = 0; | |
int memmap_on (void *addr) { | |
alloc_fd = open("test.mmap", O_CREAT | O_RDWR , 0664); | |
ftruncate( alloc_fd , ALLOC_SPACE ); | |
alloc_base = mmap( addr, ALLOC_SPACE, PROT_READ | PROT_WRITE, MAP_SHARED, alloc_fd, 0); | |
if (alloc_base != addr) { printf( "Unable to obtain requested block."); exit(3); } | |
// reserve first two records for base address and top pointer (for saved file) | |
alloc_top = alloc_base; | |
alloc_mmap = 1; | |
} | |
int memmap_off () { | |
alloc_mmap = 0; | |
munmap(alloc_base, alloc_top - alloc_base); | |
close(alloc_fd); | |
} | |
void * mmmalloc(size_t size) { | |
if (alloc_mmap) { | |
// should be something here to resize the mmap when needed. | |
// or at least check for available space | |
void * ret = alloc_top; | |
alloc_top += size; | |
return ret; | |
} else { // mmap is turned off | |
// do a normal malloc and return the result | |
} | |
} | |
void * mmfree(void * p) { | |
if (alloc_mmap) { | |
// Graphs are grow-only in memmap mode | |
printf( "You should not be freeing in mmaped mode!\n" ); | |
} else { | |
// a normal call to 'free' | |
} | |
} | |
int main () { | |
typedef struct node { int payload; struct node *next; } node; | |
int i; | |
node *head, *curr, *list; | |
memmap_on( OSX_BASE_BIG ); | |
list = (node*) malloc(sizeof(struct node)); | |
curr = list; | |
for (i=0; i<500; i++) { | |
// comment out the following two lines, then rerun a second time. | |
curr->payload = (i % 26) + 'A'; | |
curr->next = (node*) malloc(sizeof(node)); | |
printf("%c ", curr->payload); | |
curr = curr->next; | |
} | |
printf("\n"); | |
memmap_off(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment