Skip to content

Commit

Permalink
Added little memory management system.
Browse files Browse the repository at this point in the history
And example how the new feature can be used
is given in examples/hugepages.cpp.
  • Loading branch information
Simon Gog committed Aug 30, 2012
1 parent fca2cbb commit 2e58639
Show file tree
Hide file tree
Showing 4 changed files with 251 additions and 34 deletions.
43 changes: 43 additions & 0 deletions examples/hugepages.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <sdsl/int_vector.hpp>
#include <sdsl/suffixtrees.hpp>
#include <sdsl/wt_rlmn.hpp>
#include <iostream>
#include <string>

using namespace sdsl;
using namespace std;

template<class tCsa>
void do_something(const tCsa &csa){
uint64_t sum=0;
for(size_t i=0; i<csa.size();++i){
sum+=csa[i];
}
cout<<"sum="<<sum<<endl;
}

int main(int argc, char** argv){
// util::verbose = true;
{
bit_vector b(32,1);
cout << b << endl;
}
{
bit_vector b(32,0);
bool mapped = mm::map_hp();
if ( mapped ) mm::unmap_hp();
cout << b << endl;
}
bool mapped;
// bool mapped = mm::map_hp();
// if( mapped ) mm::unmap_hp();

csa_wt<wt_rlmn<> > csa;
construct_csa(string(argv[1]), csa);
do_something(csa); // before it is mapped
mapped = mm::map_hp();
do_something(csa); // while it is mapped
if ( mapped ) mm::unmap_hp();
do_something(csa); // after it is unmapped
util::clear(csa);
}
43 changes: 9 additions & 34 deletions include/sdsl/int_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
#include "testutils.hpp"
#include "uintx_t.hpp"
#include "structure_tree.hpp"

#include "memory_management.hpp"

#include <iosfwd> // forward declaration of ostream
#include <stdexcept> // for exceptions
#include <iostream> // for cerr
Expand All @@ -58,6 +61,8 @@ typedef uint64_t std_size_type_for_int_vector;
template<uint8_t fixedIntWidth=0, class size_type_class = std_size_type_for_int_vector>
class int_vector; // forward declaration

template<class int_vector_type>
class mm_item; // forward declaration

namespace algorithm
{
Expand Down Expand Up @@ -334,6 +339,7 @@ class int_vector
friend class coder::fibonacci;
friend class coder::ternary;
friend class int_vector_file_buffer<fixedIntWidth, size_type_class>;
friend class mm_item<int_vector>;
//! Operator to create an int_vector<1> (aka bit_vector) from an input stream.
friend std::istream& operator>>(std::istream&, int_vector<1>&);
friend void util::set_random_bits<int_vector>(int_vector& v, int);
Expand Down Expand Up @@ -365,40 +371,6 @@ class int_vector
//! Destructor for int_vector.
~int_vector();

bool map_it(){
size_t len = (((m_size+64)>>6)<<3);
size_t hpgs= (len+HUGE_LEN-1)/HUGE_LEN; // number of huge pages required to store the data
uint64_t *data = (uint64_t*)mmap(NULL, hpgs*HUGE_LEN, HUGE_PROTECTION, HUGE_FLAGS, 0, 0);
if (data == MAP_FAILED) {
std::cout << "mmap was not successful" << std::endl;
return false;
}
if ( m_data != NULL ){
memcpy(data, m_data, len); // copy old data
free(m_data);
m_data = data;
}
return true;
}

bool unmap_it(){
size_t len = (((m_size+64)>>6)<<3);
size_t hpgs= (len+HUGE_LEN-1)/HUGE_LEN; // number of huge pages
if ( util::verbose ){
std::cerr<<"unmap int_vector of size "<< len <<std::endl;
std::cerr<<"m_data="<<m_data<<std::endl;
}
uint64_t* tmp_data = (uint64_t*)malloc(len); // allocate memory for m_data
memcpy(tmp_data, m_data, len); // copy data from the mmapped region
int ret = munmap((void*)m_data, hpgs*HUGE_LEN );
if ( ret == -1 ){
perror("Unmap failed");
return false;
}
m_data = tmp_data;
return true;
}

//! Equivalent to size() == 0.
/*! Required for the STL Container Concept
\sa size()
Expand Down Expand Up @@ -1121,6 +1093,7 @@ inline std::istream& operator>>(std::istream &in, int_vector<1> &v){
template<uint8_t fixedIntWidth, class size_type_class>
inline int_vector<fixedIntWidth,size_type_class>::int_vector(size_type elements, value_type default_value, uint8_t intWidth):m_size(0), m_data(NULL), m_int_width(intWidth)
{
mm::add( this );
int_vector_trait<fixedIntWidth,size_type_class>::set_int_width(m_int_width, intWidth);
resize(elements);
if (default_value == 0) {
Expand All @@ -1135,6 +1108,7 @@ inline int_vector<fixedIntWidth,size_type_class>::int_vector(size_type elements,
template<uint8_t fixedIntWidth, class size_type_class>
inline int_vector<fixedIntWidth,size_type_class>::int_vector(const int_vector& v):m_size(0), m_data(NULL), m_int_width(v.m_int_width)
{
mm::add( this );
bit_resize(v.bit_size());
if (v.capacity() > 0) {
if (memcpy(m_data, v.data() ,v.capacity()/8)==NULL) {
Expand Down Expand Up @@ -1164,6 +1138,7 @@ int_vector<fixedIntWidth,size_type_class>& int_vector<fixedIntWidth,size_type_cl
template<uint8_t fixedIntWidth, class size_type_class>
int_vector<fixedIntWidth,size_type_class>::~int_vector()
{
mm::remove( this );
if (m_data != NULL) {
free(m_data); //fixed delete
}
Expand Down
119 changes: 119 additions & 0 deletions include/sdsl/memory_management.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*!\file memory_management.hpp
\brief memory_management.hpp contains two function for allocating and deallocating memory
\author Your name
*/
#ifndef INCLUDED_MEMORY_MANAGEMENT
#define INCLUDED_MEMORY_MANAGEMENT

#include "uintx_t.hpp"
#include "util.hpp"
#include <map>
#include <iostream>
using std::cout;
using std::endl;

namespace sdsl{

class mm_item_base{
public:
mm_item_base(){};
virtual bool map_hp(uint64_t*&){return false;};// const = 0;
virtual bool unmap_hp(){return false;};// const = 0;
virtual ~mm_item_base(){};
virtual uint64_t size(){return 0;};
};

template<class int_vector_type>
class mm_item : public mm_item_base{
private:
int_vector_type *m_v;
public:
explicit mm_item(int_vector_type *v):m_v(v){}
~mm_item(){ }

//! Map content of int_vector to a hugepage starting at address addr
/*!
* Details: The content of the corresponding int_vector of mm_item
* is copied into a hugepage starting at address addr.
* The string position in the hugepage is then increased
* by the number of bytes used by the int_vector.
* So addr is the new starting address for the next
* mm_item which have to be mapped.
*/
bool map_hp(uint64_t*& addr){
uint64_t len = size();
if ( m_v->m_data != NULL ){
memcpy((char*)addr, m_v->m_data, len); // copy old data
free(m_v->m_data);
m_v->m_data = addr;
addr += (len/8);
}
return true;
}

//!
bool unmap_hp(){
uint64_t len = size();
if ( util::verbose ){
std::cerr<<"unmap int_vector of size "<< len <<std::endl;
std::cerr<<"m_data="<<m_v->m_data<<std::endl;
}
uint64_t* tmp_data = (uint64_t*)malloc(len); // allocate memory for m_data
memcpy(tmp_data, m_v->m_data, len); // copy data from the mmapped region
m_v->m_data = tmp_data;
return true;
}

uint64_t size(){
return ((m_v->bit_size()+63)>>6)<<3;
}
};

class mm_initializer; // forward declaration of initialization helper

// memory management class
class mm{
friend class mm_initializer;
typedef std::map<uint64_t, mm_item_base*> tMVecItem;
static tMVecItem m_items;
static uint64_t m_total_memory;
static uint64_t *m_data;
public:
mm();

template<class int_vector_type>
static void add(int_vector_type *v){
if( mm::m_items.find((uint64_t)v) == mm::m_items.end() ){
mm_item_base* item = new mm_item<int_vector_type>(v);
if(util::verbose) cout << "mm::add: add vector " << v << endl;
mm::m_items[(uint64_t)v] = item;
}else{
if(util::verbose) cout << "mm::add: mm_item is already in the set" << endl;
}
}

template<class int_vector_type>
static void remove(int_vector_type *v){
if( mm::m_items.find((uint64_t)v) != mm::m_items.end() ){
if( util::verbose ){ cout << "mm:remove: remove vector " << v << endl; };
mm_item_base* item = m_items[(uint64_t)v];
mm::m_items.erase((uint64_t)v);
delete item;
}else{
if( util::verbose ){ cout << "mm:remove: mm_item is not in the set" << endl; };
}
}

static bool map_hp();
static bool unmap_hp();
};

static class mm_initializer{
public:
mm_initializer ();
~mm_initializer ();
} initializer;

} // end namespace

#endif
80 changes: 80 additions & 0 deletions lib/memory_management.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#include "sdsl/memory_management.hpp"

#include <cstdlib> // for malloc and free
#include <sys/mman.h>

#define HUGE_LEN 1073741824
#define HUGE_PROTECTION (PROT_READ | PROT_WRITE)
#define HUGE_FLAGS (MAP_HUGETLB | MAP_ANONYMOUS | MAP_PRIVATE)

//! Namespace for the succinct data structure library
namespace sdsl
{
static int nifty_counter;
std::map<uint64_t, mm_item_base*> mm::m_items;
uint64_t mm::m_total_memory;
uint64_t *mm::m_data;

mm_initializer::mm_initializer(){
if ( 0 == nifty_counter++ ){
// initialize static members object here
// mm::m_items.clear();
mm::m_total_memory = 0;
mm::m_data = NULL;
}
}
mm_initializer::~mm_initializer(){
if ( 0 == --nifty_counter ){
// clean up
}
}

bool mm::map_hp(){
m_total_memory = 0; // memory of all int_vectors
for(tMVecItem::const_iterator it=m_items.begin(); it!=m_items.end(); ++it){
m_total_memory += it->second->size();
}
if(util::verbose){
std::cout<<"m_total_memory"<<m_total_memory<<std::endl;
}
size_t hpgs= (m_total_memory+HUGE_LEN-1)/HUGE_LEN; // number of huge pages required to store the int_vectors
m_data = (uint64_t*)mmap(NULL, hpgs*HUGE_LEN, HUGE_PROTECTION, HUGE_FLAGS, 0, 0);
if (m_data == MAP_FAILED) {
std::cout << "mmap was not successful" << std::endl;
return false;
}else{
if( util::verbose ){
std::cerr<<"map " << m_total_memory << " bytes" << std::endl;
}
}
// map int_vectors
uint64_t *addr = m_data;
bool success = true;
for(tMVecItem::const_iterator it=m_items.begin(); it!=m_items.end(); ++it){
// std::cerr<<"addr = "<< addr << std::endl;
success = success && it->second->map_hp( addr );
}
return success;
}

bool mm::unmap_hp(){
size_t hpgs= (m_total_memory+HUGE_LEN-1)/HUGE_LEN; // number of huge pages
if ( util::verbose ){
std::cerr<<"unmap "<< m_total_memory << " bytes" <<std::endl;
std::cerr.flush();
}
bool success = true;
for(tMVecItem::const_iterator it=m_items.begin(); it!=m_items.end(); ++it){
success = success && it->second->unmap_hp();
}
// uint64_t* tmp_data = (uint64_t*)malloc(m_total_memory); // allocate memory for int_vectors
// memcpy(tmp_data, m_data, len); // copy data from the mmapped region
int ret = munmap((void*)m_data, hpgs*HUGE_LEN );
if ( ret == -1 ){
perror("Unmap failed");
return false;
}
return success;
}

} // end namespace

0 comments on commit 2e58639

Please sign in to comment.