Skip to content

Commit

Permalink
Have one version of hashtable. But performance is not good, due to th…
Browse files Browse the repository at this point in the history
…e expensiveness of getting callsite. Even with the shortcut, it is still slow for canneal.
  • Loading branch information
tongping committed Dec 19, 2019
1 parent 16e55cd commit eed85d7
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 41 deletions.
20 changes: 10 additions & 10 deletions source/hashmap.hh
Original file line number Diff line number Diff line change
Expand Up @@ -129,19 +129,18 @@ public:
// Look up whether an entry is existing or not.
// If existing, return true. *value should be carried specific value for this key.
// Otherwise, return false.
bool find(const KeyType& key, size_t keylen, ValueType* value) {
ValueType * find(const KeyType& key, size_t keylen) {
assert(_initialized == true);
size_t hindex = hashIndex(key, keylen);
struct HashBucket* first = getHashBucket(hindex);
struct Entry* entry = getEntry(first, key, keylen);
bool isFound = false;
ValueType * ret = NULL;

if(entry) {
*value = entry->value;
isFound = true;
ret = &entry->value;
}

return isFound;
return ret;
}

void * findEntry(const KeyType& key, size_t keylen) {
Expand All @@ -157,33 +156,34 @@ public:
struct Entry * entry = (struct Entry *)ptr;

if(entry) {
return entry->value;
return &entry->value;
}

return NULL;
}

// this function is customized for call stack array
ValueType* findOrAdd(const KeyType& key, size_t keylen, ValueType newval){
assert(_initialized == true);
ValueType* ret = NULL;

size_t hindex = hashIndex(key, keylen);
struct HashBucket* first = getHashBucket(hindex);
struct Entry* entry = getEntry(first, key, keylen);

struct Entry* entry = NULL;
#if LOCK_PROTECTION
first->Lock();
#endif
// Check all _buckets with the same hindex.
entry = getEntry(first, key, keylen);
if(entry == NULL) {
fprintf(stderr, "entry not exists. Now add the current one to the map\n");
// fprintf(stderr, "entry not exists. Now add the current one to the map\n");
// insert new call stack into map
entry = insertEntry(first, key, keylen, newval);
}
else {
// return the actual call stack value
ret = &entry->value;
//fprintf(stderr, "entry exists. Now return. ret %p\n", ret);
}

#if LOCK_PROTECTION
Expand Down Expand Up @@ -317,7 +317,7 @@ private:
count--;
}

fprintf(stderr, "count is %d\n", count);
//fprintf(stderr, "count is %d\n", count);
return result;
}

Expand Down
8 changes: 2 additions & 6 deletions source/libnumalloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ char * localPtrEnd;
typedef enum {
E_HEAP_INIT_NOT = 0,
E_HEAP_INIT_WORKING,
E_HEAP_INIT_DONE,
E_HEAP_NORMAL,
E_HEAP_INIT_DONE
} eHeapInitStatus;

eHeapInitStatus heapInitStatus = E_HEAP_INIT_NOT;
Expand All @@ -65,7 +64,6 @@ extern "C" int light_libc_start_main(main_fn_t main_fn, int argc, char** argv, v

selfmap::getInstance().getTextRegions();

heapInitStatus = E_HEAP_NORMAL;
return real_libc_start_main(main_fn, argc, argv, init, fini, rtld_fini, stack_end);
}

Expand Down Expand Up @@ -121,7 +119,6 @@ void heapinitialize() {
// Thread initialization, which can be occurred before or after numap heap initialization
xthread::getInstance().initialize();

fprintf(stderr, "in the end of heapinitialize()\n");
heapInitStatus = E_HEAP_INIT_DONE;
}
else {
Expand Down Expand Up @@ -154,11 +151,10 @@ void heapinitialize() {
break;

case E_HEAP_INIT_WORKING:
case E_HEAP_INIT_DONE:
ptr = Real::malloc(size);
break;

case E_HEAP_NORMAL:
case E_HEAP_INIT_DONE:
ptr = NumaHeap::getInstance().allocate(size);
//fprintf(stderr, "malloc size %ld ptr %p\n", size, ptr);
break;
Expand Down
51 changes: 40 additions & 11 deletions source/mainheap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "selfmap.hh"

#define CALLSTACK_SKIP_LEVEL 2
#define MY_DEBUG 0
int getCallStack(int depth, callstack *cs) {

// Fetch the frame address of the topmost stack frame
Expand Down Expand Up @@ -31,7 +32,7 @@ int getCallStack(int depth, callstack *cs) {

if(!selfmap::getInstance().isThisLibrary(caller_addr)){
cs->stack[level++] = caller_addr;
fprintf(stderr, "calleraddr %p\n", caller_addr);
//fprintf(stderr, "calleraddr %p\n", caller_addr);
}

if(prev_frame == prev_frame->prev){
Expand All @@ -42,7 +43,7 @@ int getCallStack(int depth, callstack *cs) {
prev_frame = prev_frame->prev;
}

fprintf(stderr, "level is %d depth is %d\n", level, depth);
// fprintf(stderr, "level is %d depth is %d\n", level, depth);

if(level < depth) {
for(int i=level; i<depth; i++) {
Expand All @@ -55,11 +56,11 @@ int getCallStack(int depth, callstack *cs) {


void * MainHeap::allocate(size_t size) {
void * ptr = NULL;

void * ptr = NULL;

#if MY_DEBUG
// Get the callstack right now.
callstack cs;
//void * stack[2];
struct CallsiteInfo info;

// Collect the callstack
Expand All @@ -72,15 +73,21 @@ int getCallStack(int depth, callstack *cs) {
// Check whether this callstack is shared or not
// If not, then we will use the normal allocation, instead of the shared heap.
if(oldinfo) {
fprintf(stderr, "oldinfo exists????\n");
if(oldinfo->isPrivateCallsite()) {
//while(1) { ; }
// fprintf(stderr, "***********a private callsite*********\n");
return NULL;
}
else {
oldinfo->updateAlloc();
}
}
#endif
//_specialMalloc++;

//if(_specialMalloc % 10000 == 0) {
// fprintf(stderr, "specialMalloc %ld\n", _specialMalloc);
// }
// If the callstack is shared or unknown, then we will allocated from the interleaved heap.
// Allocate from the freelist at first.
int sc;
Expand Down Expand Up @@ -117,20 +124,42 @@ int getCallStack(int depth, callstack *cs) {
}
}


#if MY_DEBUG
// We will only add the first object into the objectsHashMap to speedup the search later.
if(!oldinfo) {
void * hashentry = _callsiteMap.findEntry(cs, sizeof(cs));
CallsiteInfo* info = _callsiteMap.find(cs, sizeof(cs));
ObjectInfo objInfo(_mhpSequence, info);

fprintf(stderr, "Insert the object: size %ld ptr %p entry %p\n", size, ptr, hashentry);
// For the performance reason, we will save the entry of another hashmap there.
_objectsMap.insert((void *)ptr, sizeof(callstack *), hashentry);
_objectsMap.insert((void *)ptr, sizeof(void *), objInfo);
}
//fprintf(stderr, "malloc %ld ptr %p\n", size, ptr);
#endif
return ptr;
}

void MainHeap::deallocate(void * ptr) {
#if MY_DEBUG
// Check the phase information of this deallocation.
// If the current phase is the same as the allocation phase,
// then we will mark the corresponding callsite as private
if(_mainHeapPhase) {
ObjectInfo * info = _objectsMap.find((void *)ptr, sizeof(void *));

if(info) {
// fprintf(stderr, "in deallocate, with object phase %d\n", info->getSequence());
if(info->getSequence() == _mhpSequence) {
// Set the corresponding callsite to private, avoiding subsequent
// allocations from the special heap.
CallsiteInfo * csInfo = info->getCallsiteInfo();
//fprintf(stderr, "csInfo is at %p\n", csInfo);
csInfo->setPrivateCallsite();
}
}

// Now simply delete this entry
_objectsMap.erase((void *)ptr, sizeof(void *));
}
#endif
if(ptr <= _bpMiddleEnd) {
int sc = getSizeClass(ptr);
//fprintf(stderr, "free ptr %p with size %lx\n", ptr, getSize(ptr));
Expand Down
44 changes: 42 additions & 2 deletions source/mainheap.hh
Original file line number Diff line number Diff line change
Expand Up @@ -149,13 +149,18 @@ class MainHeap {
int _nodeindex;
int _bagShiftBits;

// We will update the phase information.
bool _mainHeapPhase;
int _mhpSequence; // main heap phase sequence number

class mtBigObjects _bigObjects;

// Currently, size class is from 2^4 to 2^19 (512 KB), with 16 sizes in total.
PerNodeSizeClass ** _sizes;

// The size of bag will be BAG_SIZE_SMALL_OBJECTS
PerBagInfo * _info;
unsigned long _specialMalloc;

class CallsiteInfo {
bool _isPrivate; // Is known to be private or not.
Expand All @@ -174,6 +179,10 @@ class MainHeap {
inline void updateAlloc() {
_allocNum++;
}

inline void setPrivateCallsite() {
_isPrivate = true;
}
};

class localAllocator {
Expand All @@ -192,9 +201,26 @@ class MainHeap {
typedef HashMap<callstack, CallsiteInfo, localAllocator> CallsiteMap;
CallsiteMap _callsiteMap;

class ObjectInfo {
public:
int _allocSequence;
CallsiteInfo * _callsiteInfo;

ObjectInfo(int sequence, CallsiteInfo * info) {
_allocSequence = sequence;
_callsiteInfo = info;
}

int getSequence() {
return _allocSequence;
}

CallsiteInfo * getCallsiteInfo() {
return _callsiteInfo;
}
};
// ObjectsMap will save the mapping between the object address and its callsite
typedef HashMap<void *, void *, localAllocator> ObjectsHashMap;
typedef HashMap<void *, ObjectInfo, localAllocator> ObjectsHashMap;
ObjectsHashMap _objectsMap;

public:
Expand All @@ -221,6 +247,7 @@ class MainHeap {
return size;
}


void initialize(int nodeindex, void * begin) {
// Save the heap related information
_begin = (char *)begin;
Expand All @@ -231,6 +258,7 @@ class MainHeap {
//_bpSmall = (char *)MM::mmapAllocatePrivate(SIZE_PER_SPAN, (void *)_begin);
_bpSmallEnd = _bpSmall + SIZE_PER_SPAN;
// fprintf(stderr, "_bpSmall is %p\n", _bpSmall);
_specialMalloc = 0;

_callsiteMap.initialize(HashFuncs::hashCallStackT, HashFuncs::compareCallStackT);
_objectsMap.initialize(HashFuncs::hashAddr, HashFuncs::compareAddr);
Expand Down Expand Up @@ -300,10 +328,22 @@ class MainHeap {
classSize *= 2;
}

_mainHeapPhase = true;
_mhpSequence = 0; // main heap phase sequence number

// Now initialize the PerBagInfo
_info = (PerBagInfo *)ptr;
}


void stopPhase() {
_mainHeapPhase = false;
}

void updatePhase() {
_mainHeapPhase = true;
_mhpSequence++;
}

// We will reserve a block of memory to store the size information of each chunk,
// in the unit of four pages.
int getSizeClass(void * ptr) {
Expand Down
Loading

1 comment on commit eed85d7

@tongping
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good version for collecting callsites, and performing check. Possibly will have some uses in the future.

Please sign in to comment.