コード例 #1
0
ファイル: pascal_hash_table.c プロジェクト: dryman/opic
PascalHashTable*
PHNew(OPHeap* heap, uint64_t num_objects, double load,
      size_t key_inline_size, size_t valsize)
{
  PascalHashTable* table;
  uint64_t capacity;
  uint32_t capacity_clz, capacity_ms4b, capacity_msb;
  size_t bucket_size;
  void* bucket_ptr;

  op_assert(load > 0.0 && load < 1.0,
            "load %lf must within close interval (0.0, 1.0)\n", load);
  capacity = (uint64_t)(num_objects / load);
  if (capacity < 8)
    capacity = 8;
  capacity_clz = __builtin_clzl(capacity);
  capacity_msb = 64 - capacity_clz;
  capacity_ms4b = round_up_div(capacity, 1UL << (capacity_msb - 4));
  capacity = (uint64_t)capacity_ms4b << (capacity_msb - 4);

  bucket_size = sizeof(oplenref_t) + key_inline_size + valsize;

  table = OPCalloc(heap, 1, sizeof(PascalHashTable));
  if (!table)
    return NULL;
  bucket_ptr = OPCalloc(heap, 1, bucket_size * capacity);
  if (!bucket_ptr)
    {
      OPDealloc(table);
      return NULL;
    }
  table->bucket_ref = OPPtr2Ref(bucket_ptr);
  table->large_data_threshold = DEFAULT_LARGE_DATA_THRESHOLD;
  table->capacity_clz = capacity_clz;
  table->capacity_ms4b = capacity_ms4b;
  table->objcnt_high = (uint64_t)(capacity * load);
  table->objcnt_low = capacity * 2 / 10;
  table->key_inline_size = key_inline_size;
  table->valsize = valsize;
  return table;
}
コード例 #2
0
ファイル: alloc.c プロジェクト: Aurametrix/Alg-C
OPHeap* heap;
// Initialize a 64GB OPIC heap via mmap
OPHeapNew(&heap);
// pointer for accessing the object
int *a_ptr = OPMalloc(heap, sizeof(int));
// deallocate an object does not require specifying the heap
OPDealloc(a_ptr);

void OPHeapWrite(OPHeap* heap, FILE* stream);
bool OPHeapRead(OPHeap** heap_ref, FILE* stream);

// Convert the pointer to a offset to the OPHeap base address
// The pointer must be a pointer created by OPHeap
opref_t a_ref = OPPtr2Ref(a_ptr);
// Add the offset a_ref with OPHeap base address to restore
// the pointer.
int* a_ptr = OPRef2Ptr(heap, a_ref);

**
 * @relates OPHeap
 * @brief Store a pointer to a root pointer slot in OPHeap.
 *
 * @param heap OPHeap instance.
 * @param ptr the pointer we want to store in root pointer slot.
 * @param pos index in the root pointer slot. 0 <= pos < 8.
 */
void OPHeapStorePtr(OPHeap* heap, void* ptr, int pos);

/**
 * @relates OPHeap
 * @brief Restore a pointer from specified root pointer slot.
コード例 #3
0
ファイル: pascal_hash_table.c プロジェクト: dryman/opic
static bool
PHSizeDown(PascalHashTable* table, OPHash hasher)
{
  const size_t key_inline_size = table->key_inline_size;
  const size_t valsize = table->valsize;
  const size_t bucket_size = sizeof(oplenref_t) + key_inline_size + valsize;
  uint8_t* old_buckets;
  uint8_t* new_buckets;
  uint8_t new_capacity_ms4b, new_capacity_clz;
  uint64_t old_capacity, new_capacity;
  oplenref_t *recref;
  bool resized;

  old_capacity = PHCapacity(table);
  old_buckets = OPRef2Ptr(table, table->bucket_ref);
  op_assert(old_capacity > 16,
            "Can not resize smaller than 16, but got old_capacity %"
            PRIu64 "\n", old_capacity);

  switch(table->capacity_ms4b)
    {
    case 8:  // new load 0.45
    case 9:  // new load 0.50
    case 10: // new load 0.55
    case 11: // new load 0.60
      new_capacity_ms4b = 8;
      new_capacity_clz = table->capacity_clz + 1;
      break;
    case 12: // new load 0.40
    case 13: // new load 0.43
    case 14: // new load 0.46
    case 15: // new load 0.50
      new_capacity_ms4b = 12;
      new_capacity_clz = table->capacity_clz + 1;
      break;
    default: op_assert(false, "Unknown capacity_ms4b %d\n",
                       table->capacity_ms4b);
    }

  new_capacity = PHCapacityInternal(new_capacity_clz, new_capacity_ms4b);
  OP_LOG_INFO(logger, "Resize from %" PRIu64 " to %" PRIu64,
              old_capacity, new_capacity);
  new_buckets = OPCalloc(ObtainOPHeap(table), 1, bucket_size * new_capacity);
  if (!new_buckets)
    {
      OP_LOG_ERROR(logger, "Cannot obtain new bucket for size %" PRIu64,
                   new_capacity);
      return false;
    }

  table->objcnt = 0;
  table->objcnt_high = new_capacity * 8 / 10;
  table->objcnt_low = new_capacity * 2 / 10;
  table->capacity_clz = new_capacity_clz;
  table->capacity_ms4b = new_capacity_ms4b;
  table->longest_probes = 0;
  memset(table->stats, 0x00, sizeof(uint32_t) * PROBE_STATS_SIZE);
  table->bucket_ref = OPPtr2Ref(new_buckets);

  for (uint64_t idx = 0; idx < old_capacity; idx++)
    {
      recref = (oplenref_t*)&old_buckets[idx * bucket_size];
      if (!OPLenRefIsEmpty(*recref) &&
          !OPLenRefIsDeleted(*recref))
        {
          PHUpsertPushDown(table, hasher, &old_buckets[idx * bucket_size],
                           0, NULL, &resized);
        }
    }
  OPDealloc(old_buckets);
  return true;
}
コード例 #4
0
ファイル: pascal_hash_table.c プロジェクト: dryman/opic
static bool
PHSizeUp(PascalHashTable* table, OPHash hasher)
{
  const size_t key_inline_size = table->key_inline_size;
  const size_t valsize = table->valsize;
  const size_t bucket_size = sizeof(oplenref_t) + key_inline_size + valsize;
  const size_t large_data_threshold = table->large_data_threshold;
  uint8_t* old_buckets;
  uint8_t* new_buckets;
  oplenref_t *recref;
  bool resized;
  uint8_t new_capacity_ms4b, new_capacity_clz;
  uint64_t old_capacity, new_capacity;

  old_capacity = PHCapacity(table);
  old_buckets = OPRef2Ptr(table, table->bucket_ref);

  if (old_capacity * bucket_size >= large_data_threshold)
    {
      // increase size by 20% ~ 33%
      switch(table->capacity_ms4b)
        {
        case 8:
          new_capacity_ms4b = 10;
          new_capacity_clz = table->capacity_clz;
          break;
        case 9:
        case 10:
          new_capacity_ms4b = 12;
          new_capacity_clz = table->capacity_clz;
          break;
        case 11:
        case 12:
          new_capacity_ms4b = 14;
          new_capacity_clz = table->capacity_clz;
          break;
        case 13:
        case 14:
          new_capacity_ms4b = 8;
          new_capacity_clz = table->capacity_clz - 1;
          break;
        case 15:
          new_capacity_ms4b = 10;
          new_capacity_clz = table->capacity_clz - 1;
          break;
        default: op_assert(false, "Unknown capacity_ms4b %d\n",
                           table->capacity_ms4b);
        }
    }
  else
    {
      new_capacity_ms4b = 8;
      new_capacity_clz = table->capacity_ms4b == 8 ?
        table->capacity_clz - 1 : table->capacity_clz - 2;
    }
  new_capacity = PHCapacityInternal(new_capacity_clz, new_capacity_ms4b);
  OP_LOG_INFO(logger, "Resize from %" PRIu64 " to %" PRIu64,
              old_capacity, new_capacity);

  new_buckets = OPCalloc(ObtainOPHeap(table), 1, bucket_size * new_capacity);
  if (!new_buckets)
    {
      OP_LOG_ERROR(logger, "Cannot obtain new bucket for size %" PRIu64,
                   new_capacity);
      return false;
    }

  table->objcnt = 0;
  table->objcnt_high = new_capacity * 8 / 10;
  table->objcnt_low = new_capacity * 2 / 10;
  table->capacity_clz = new_capacity_clz;
  table->capacity_ms4b = new_capacity_ms4b;
  table->longest_probes = 0;
  memset(table->stats, 0x00, sizeof(uint32_t) * PROBE_STATS_SIZE);
  table->bucket_ref = OPPtr2Ref(new_buckets);

  for (uint64_t idx = 0; idx < old_capacity; idx++)
    {
      recref = (oplenref_t*)&old_buckets[idx * bucket_size];
      if (!OPLenRefIsEmpty(*recref) &&
          !OPLenRefIsDeleted(*recref))
        {
          PHUpsertPushDown(table, hasher, &old_buckets[idx * bucket_size],
                           0, NULL, &resized);
        }
    }
  OPDealloc(old_buckets);
  return true;
}