<commit_before>#include "multiverso/util/allocator.h"

#include "multiverso/util/log.h"
#include "multiverso/util/configure.h"

namespace multiverso {

MV_DEFINE_int(allocator_alignment, 16, "alignment for align malloc");

inline char* AlignMalloc(size_t size) {
#ifdef _MSC_VER 
  return (char*)_aligned_malloc(size, 
    MV_CONFIG_allocator_alignment);
#else
  void *data;
  CHECK(posix_memalign(&data, 
    MV_CONFIG_allocator_alignment, size) == 0);
  return (char*)data;
#endif
}

inline void AlignFree(char *data) {
#ifdef _MSC_VER 
  _aligned_free(data);
#else
  free(data);
#endif
}

inline FreeList::FreeList(size_t size) :
size_(size) {
  free_ = new MemoryBlock(size, this);
}

FreeList::~FreeList() {
  MemoryBlock*move = free_, *next;
  while (move) {
    next = move->next;
    delete move;
    move = next;
  }
}

inline char* FreeList::Pop() {
  std::lock_guard<std::mutex> lock(mutex_);
  if (free_ == nullptr) {
    free_ = new MemoryBlock(size_, this);
  }
  char* data = free_->data();
  free_ = free_->next;
  return data;
}

inline void FreeList::Push(MemoryBlock*block) {
  std::lock_guard<std::mutex> lock(mutex_);
  block->next = free_;
  free_ = block;
}

inline MemoryBlock::MemoryBlock(size_t size, FreeList* list) :
next(nullptr), ref_(0) {
  data_ = AlignMalloc(size + header_size_);
  *(FreeList**)(data_) = list;
  *(MemoryBlock**)(data_ + g_pointer_size) = this;
}

MemoryBlock::~MemoryBlock() {
  AlignFree(data_);
}

inline void MemoryBlock::Unlink() {
  if ((--ref_) == 0) {
    (*(FreeList**)data_)->Push(this);
  }
}

inline char* MemoryBlock::data() {
  ++ref_;
  return data_ + header_size_;
}

inline void MemoryBlock::Link() {
  ++ref_;
}

char* SmartAllocator::Alloc(size_t size) {
  if (size <= 32) {
    size = 32;
  }
  else { // 2^n
    size -= 1;
    size |= size >> 32;
    size |= size >> 16;
    size |= size >> 8;
    size |= size >> 4;
    size |= size >> 2;
    size |= size >> 1;
    size += 1;
  }

  std::unique_lock<std::mutex> lock(mutex_);
  if (pools_[size] == nullptr) {
    pools_[size] = new FreeList(size);
  }
  lock.unlock();

  return pools_[size]->Pop();
}

void SmartAllocator::Free(char *data) {
  (*(MemoryBlock**)(data - g_pointer_size))->Unlink();
}

void SmartAllocator::Refer(char *data) {
  (*(MemoryBlock**)(data - g_pointer_size))->Link();
}

SmartAllocator::~SmartAllocator() {
  Log::Debug("~SmartAllocator, final pool size: %d\n", pools_.size());
  for (auto i : pools_) {
    delete i.second;
  }
}

char* Allocator::Alloc(size_t size) {
  char* data = AlignMalloc(size + header_size_);
  // record ref
  *(std::atomic<int>**)data = new std::atomic<int>(1);
  return data + header_size_;
}
<commit_msg>Little change<commit_after>#include "multiverso/util/allocator.h"

#include "multiverso/util/log.h"
#include "multiverso/util/configure.h"

namespace multiverso {

MV_DEFINE_int(allocator_alignment, 16, "alignment for align malloc");

inline char* AlignMalloc(size_t size) {
#ifdef _MSC_VER 
  return (char*)_aligned_malloc(size, 
    MV_CONFIG_allocator_alignment);
#else
  void *data;
  CHECK(posix_memalign(&data, 
    MV_CONFIG_allocator_alignment, size) == 0);
  return (char*)data;
#endif
}

inline void AlignFree(char *data) {
#ifdef _MSC_VER 
  _aligned_free(data);
#else
  free(data);
#endif
}

inline FreeList::FreeList(size_t size) :
size_(size) {
  free_ = new MemoryBlock(size, this);
}

FreeList::~FreeList() {
  MemoryBlock*move = free_, *next;
  while (move) {
    next = move->next;
    delete move;
    move = next;
  }
}

inline char* FreeList::Pop() {
  std::lock_guard<std::mutex> lock(mutex_);
  if (free_ == nullptr) {
    free_ = new MemoryBlock(size_, this);
  }
  char* data = free_->data();
  free_ = free_->next;
  return data;
}

inline void FreeList::Push(MemoryBlock*block) {
  std::lock_guard<std::mutex> lock(mutex_);
  block->next = free_;
  free_ = block;
}

inline MemoryBlock::MemoryBlock(size_t size, FreeList* list) :
next(nullptr), ref_(0) {
  data_ = AlignMalloc(size + header_size_);
  *(FreeList**)(data_) = list;
  *(MemoryBlock**)(data_ + g_pointer_size) = this;
}

MemoryBlock::~MemoryBlock() {
  AlignFree(data_);
}

inline void MemoryBlock::Unlink() {
  if ((--ref_) == 0) {
    (*(FreeList**)data_)->Push(this);
  }
}

inline char* MemoryBlock::data() {
  ++ref_;
  return data_ + header_size_;
}

inline void MemoryBlock::Link() {
  ++ref_;
}

char* SmartAllocator::Alloc(size_t size) {
  if (size <= 32) {
    size = 32;
  }
  else { // 2^n
    size -= 1;
    size |= size >> 32;
    size |= size >> 16;
    size |= size >> 8;
    size |= size >> 4;
    size |= size >> 2;
    size |= size >> 1;
    size += 1;
  }

  {
    std::lock_guard<std::mutex> lock(mutex_);
    if (pools_[size] == nullptr) {
      pools_[size] = new FreeList(size);
    }
  }

  return pools_[size]->Pop();
}

void SmartAllocator::Free(char *data) {
  (*(MemoryBlock**)(data - g_pointer_size))->Unlink();
}

void SmartAllocator::Refer(char *data) {
  (*(MemoryBlock**)(data - g_pointer_size))->Link();
}

SmartAllocator::~SmartAllocator() {
  Log::Debug("~SmartAllocator, final pool size: %d\n", pools_.size());
  for (auto i : pools_) {
    delete i.second;
  }
}

char* Allocator::Alloc(size_t size) {
  char* data = AlignMalloc(size + header_size_);
  // record ref
  *(std::atomic<int>**)data = new std::atomic<int>(1);
  return data + header_size_;
}

{'fraction_non_alphanumeric': 0.1736214605067064, 'fraction_numerical': 0.00782414307004471, 'mean_word_length': 4.10361216730038, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2846090', 'n_tokens_mistral': 2059, 'n_tokens_neox': 1979, 'n_words': 414}