Skip to content

Instantly share code, notes, and snippets.

@abyrd
Created August 11, 2009 16:14
Show Gist options
  • Save abyrd/165929 to your computer and use it in GitHub Desktop.
Save abyrd/165929 to your computer and use it in GitHub Desktop.
Proof of concept for mmapping Graph structures
#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);
}
}
#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