quickstep-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cramja <...@git.apache.org>
Subject [GitHub] incubator-quickstep pull request #100: Refactor bulk insert for SplitRowStor...
Date Tue, 20 Sep 2016 22:13:05 GMT
Github user cramja commented on a diff in the pull request:

    https://github.com/apache/incubator-quickstep/pull/100#discussion_r79724504
  
    --- Diff: storage/SplitRowStoreTupleStorageSubBlock.cpp ---
    @@ -194,379 +257,125 @@ TupleStorageSubBlock::InsertResult SplitRowStoreTupleStorageSubBlock::insertTupl
     }
     
     tuple_id SplitRowStoreTupleStorageSubBlock::bulkInsertTuples(ValueAccessor *accessor)
{
    -  const tuple_id original_num_tuples = header_->num_tuples;
    -  tuple_id pos = 0;
    -
    -  InvokeOnAnyValueAccessor(
    -      accessor,
    -      [&](auto *accessor) -> void {  // NOLINT(build/c++11)
    -    if (relation_.hasNullableAttributes()) {
    -      if (relation_.isVariableLength()) {
    -        while (accessor->next()) {
    -          // If packed, insert at the end of the slot array, otherwise find the
    -          // first hole.
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    -          const std::size_t tuple_variable_bytes
    -              = CalculateVariableSize<decltype(*accessor), true>(relation_, *accessor);
    -          if (!this->spaceToInsert(pos, tuple_variable_bytes)) {
    -            accessor->previous();
    -            break;
    -          }
    -          // Allocate variable-length storage.
    -          header_->variable_length_bytes_allocated += tuple_variable_bytes;
    -
    -          // Find the slot and locate its sub-structures.
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          BitVector<true> tuple_null_bitmap(tuple_slot,
    -                                            relation_.numNullableAttributes());
    -          tuple_null_bitmap.clear();
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -          std::uint32_t *variable_length_info_array = reinterpret_cast<std::uint32_t*>(
    -              fixed_length_attr_storage + relation_.getFixedByteLength());
    -          // Start writing variable-length data at the beginning of the newly
    -          // allocated range.
    -          std::uint32_t current_variable_position
    -              = tuple_storage_bytes_ - header_->variable_length_bytes_allocated;
    -
    -          attribute_id accessor_attr_id = 0;
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++accessor_attr_id) {
    -            const int nullable_idx = relation_.getNullableAttributeIndex(attr_it->getID());
    -            const int variable_idx = relation_.getVariableLengthAttributeIndex(attr_it->getID());
    -            TypedValue attr_value(accessor->getTypedValue(accessor_attr_id));
    -            if ((nullable_idx != -1) && (attr_value.isNull())) {
    -              // Set null bit and move on.
    -              tuple_null_bitmap.setBit(nullable_idx, true);
    -              continue;
    -            }
    -            if (variable_idx != -1) {
    -              // Write offset and size into the slot, then copy the actual
    -              // value into the variable-length storage region.
    -              const std::size_t attr_size = attr_value.getDataSize();
    -              variable_length_info_array[variable_idx << 1] = current_variable_position;
    -              variable_length_info_array[(variable_idx << 1) + 1] = attr_size;
    -              attr_value.copyInto(static_cast<char*>(tuple_storage_) + current_variable_position);
    -              current_variable_position += attr_size;
    -            } else {
    -              // Copy fixed-length value directly into the slot.
    -              attr_value.copyInto(fixed_length_attr_storage
    -                                  + relation_.getFixedLengthAttributeOffset(attr_it->getID()));
    -            }
    -          }
    -          // Update occupancy bitmap and header.
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    -          }
    -        }
    -      } else {
    -        // Same as above, but skip variable-length checks.
    -        while (accessor->next()) {
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    -          if (!this->spaceToInsert(pos, 0)) {
    -            accessor->previous();
    -            break;
    -          }
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          BitVector<true> tuple_null_bitmap(tuple_slot,
    -                                            relation_.numNullableAttributes());
    -          tuple_null_bitmap.clear();
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -
    -          attribute_id accessor_attr_id = 0;
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++accessor_attr_id) {
    -            const int nullable_idx = relation_.getNullableAttributeIndex(attr_it->getID());
    -            if (nullable_idx != -1) {
    -              const void *attr_value = accessor->template getUntypedValue<true>(accessor_attr_id);
    -              if (attr_value == nullptr) {
    -                tuple_null_bitmap.setBit(nullable_idx, true);
    -              } else {
    -                std::memcpy(fixed_length_attr_storage
    -                                + relation_.getFixedLengthAttributeOffset(attr_it->getID()),
    -                            attr_value,
    -                            attr_it->getType().maximumByteLength());
    -              }
    -            } else {
    -              const void *attr_value = accessor->template getUntypedValue<false>(accessor_attr_id);
    -              std::memcpy(fixed_length_attr_storage
    -                              + relation_.getFixedLengthAttributeOffset(attr_it->getID()),
    -                          attr_value,
    -                          attr_it->getType().maximumByteLength());
    -            }
    -          }
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    -          }
    -        }
    -      }
    -    } else {
    -      if (relation_.isVariableLength()) {
    -        // Same as most general case above, but skip null checks.
    -        while (accessor->next()) {
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    -          const std::size_t tuple_variable_bytes
    -              = CalculateVariableSize<decltype(*accessor), false>(relation_, *accessor);
    -          if (!this->spaceToInsert(pos, tuple_variable_bytes)) {
    -            accessor->previous();
    -            break;
    -          }
    -          header_->variable_length_bytes_allocated += tuple_variable_bytes;
    -
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -          std::uint32_t *variable_length_info_array = reinterpret_cast<std::uint32_t*>(
    -              fixed_length_attr_storage + relation_.getFixedByteLength());
    -          std::uint32_t current_variable_position
    -              = tuple_storage_bytes_ - header_->variable_length_bytes_allocated;
    -
    -          attribute_id accessor_attr_id = 0;
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++accessor_attr_id) {
    -            const int variable_idx = relation_.getVariableLengthAttributeIndex(attr_it->getID());
    -            TypedValue attr_value(accessor->getTypedValue(accessor_attr_id));
    -            if (variable_idx != -1) {
    -              const std::size_t attr_size = attr_value.getDataSize();
    -              variable_length_info_array[variable_idx << 1] = current_variable_position;
    -              variable_length_info_array[(variable_idx << 1) + 1] = attr_size;
    -              attr_value.copyInto(static_cast<char*>(tuple_storage_) + current_variable_position);
    -              current_variable_position += attr_size;
    -            } else {
    -              attr_value.copyInto(fixed_length_attr_storage
    -                                  + relation_.getFixedLengthAttributeOffset(attr_it->getID()));
    -            }
    -          }
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    -          }
    -        }
    -      } else {
    -        // Simplest case: skip both null and variable-length checks.
    -        while (accessor->next()) {
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    -          if (!this->spaceToInsert(pos, 0)) {
    -            accessor->previous();
    -            break;
    -          }
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -
    -          attribute_id accessor_attr_id = 0;
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++accessor_attr_id) {
    -            const void *attr_value = accessor->template getUntypedValue<false>(accessor_attr_id);
    -            std::memcpy(fixed_length_attr_storage
    -                            + relation_.getFixedLengthAttributeOffset(attr_it->getID()),
    -                        attr_value,
    -                        attr_it->getType().maximumByteLength());
    -          }
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    -          }
    -        }
    -      }
    -    }
    -  });
    -
    -  return header_->num_tuples - original_num_tuples;
    +  std::vector<attribute_id> simple_remap;
    +  for (attribute_id attr_id = 0; 
    +			attr_id < static_cast<attribute_id>(relation_.size());
    +			++attr_id) {
    +    simple_remap.push_back(attr_id);
    +  }
    +  return bulkInsertTuplesWithRemappedAttributes(simple_remap, accessor);
     }
     
     tuple_id SplitRowStoreTupleStorageSubBlock::bulkInsertTuplesWithRemappedAttributes(
         const std::vector<attribute_id> &attribute_map,
         ValueAccessor *accessor) {
    -  DEBUG_ASSERT(attribute_map.size() == relation_.size());
    +  DCHECK_EQ(relation_.size(), attribute_map.size());
       const tuple_id original_num_tuples = header_->num_tuples;
       tuple_id pos = 0;
     
    +  BasicInsertInfo insertInfo(relation_);
    +
       InvokeOnAnyValueAccessor(
    -      accessor,
    -      [&](auto *accessor) -> void {  // NOLINT(build/c++11)
    -    if (relation_.hasNullableAttributes()) {
    -      if (relation_.isVariableLength()) {
    -        while (accessor->next()) {
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    +    accessor,
    +    [&](auto *accessor) -> void {  // NOLINT(build/c++11
    +      while (accessor->next()) {
    +        // If packed, insert at the end of the slot array, otherwise find the
    +        // first hole.
    +        pos = this->isPacked() ? header_->num_tuples
    +                               : occupancy_bitmap_->firstZero(pos);
    +
    +        // Only calculate space used if needed.
    +        if (!this->spaceToInsert(pos, insertInfo.max_var_length_)) {
               const std::size_t tuple_variable_bytes
    -              = CalculateVariableSizeWithRemappedAttributes<decltype(*accessor), true>(
    -                  relation_, *accessor, attribute_map);
    +            = CalculateVariableSizeWithRemappedAttributes<decltype(*accessor), true>(relation_,
*accessor,
    +                                                                                    
attribute_map);
               if (!this->spaceToInsert(pos, tuple_variable_bytes)) {
                 accessor->previous();
                 break;
               }
    -          header_->variable_length_bytes_allocated += tuple_variable_bytes;
    -
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          BitVector<true> tuple_null_bitmap(tuple_slot,
    -                                            relation_.numNullableAttributes());
    -          tuple_null_bitmap.clear();
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -          std::uint32_t *variable_length_info_array = reinterpret_cast<std::uint32_t*>(
    -              fixed_length_attr_storage + relation_.getFixedByteLength());
    -          std::uint32_t current_variable_position
    -              = tuple_storage_bytes_ - header_->variable_length_bytes_allocated;
    -
    -          std::vector<attribute_id>::const_iterator attr_map_it = attribute_map.begin();
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++attr_map_it) {
    -            const int nullable_idx = relation_.getNullableAttributeIndex(attr_it->getID());
    -            const int variable_idx = relation_.getVariableLengthAttributeIndex(attr_it->getID());
    -            TypedValue attr_value(accessor->getTypedValue(*attr_map_it));
    -            if ((nullable_idx != -1) && (attr_value.isNull())) {
    -              tuple_null_bitmap.setBit(nullable_idx, true);
    -              continue;
    -            }
    -            if (variable_idx != -1) {
    -              const std::size_t attr_size = attr_value.getDataSize();
    -              variable_length_info_array[variable_idx << 1] = current_variable_position;
    -              variable_length_info_array[(variable_idx << 1) + 1] = attr_size;
    -              attr_value.copyInto(static_cast<char*>(tuple_storage_) + current_variable_position);
    -              current_variable_position += attr_size;
    -            } else {
    -              attr_value.copyInto(fixed_length_attr_storage
    -                                  + relation_.getFixedLengthAttributeOffset(attr_it->getID()));
    -            }
    -          }
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    -          }
             }
    -      } else {
    -        while (accessor->next()) {
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    -          if (!this->spaceToInsert(pos, 0)) {
    -            accessor->previous();
    -            break;
    -          }
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          BitVector<true> tuple_null_bitmap(tuple_slot,
    -                                            relation_.numNullableAttributes());
    -          tuple_null_bitmap.clear();
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -
    -          std::vector<attribute_id>::const_iterator attr_map_it = attribute_map.begin();
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++attr_map_it) {
    -            const int nullable_idx = relation_.getNullableAttributeIndex(attr_it->getID());
    -            if (nullable_idx != -1) {
    -              const void *attr_value = accessor->template getUntypedValue<true>(*attr_map_it);
    -              if (attr_value == nullptr) {
    -                tuple_null_bitmap.setBit(nullable_idx, true);
    -              } else {
    -                std::memcpy(fixed_length_attr_storage
    -                                + relation_.getFixedLengthAttributeOffset(attr_it->getID()),
    -                            attr_value,
    -                            attr_it->getType().maximumByteLength());
    -              }
    +
    +        // Find the slot and locate its sub-structures.
    +        void *tuple_slot = static_cast<char *>(tuple_storage_) + pos * tuple_slot_bytes_;
    +
    +        BitVector<true> tuple_null_bitmap(tuple_slot, insertInfo.num_nullable_attrs_);
    +        tuple_null_bitmap.clear();
    +        char *fixed_length_attr_storage = static_cast<char *>(tuple_slot) + insertInfo.fixed_len_offset_;
    +        std::uint32_t *variable_length_info_array =
    +          reinterpret_cast<std::uint32_t *>(static_cast<char *>(tuple_slot)
+ insertInfo.var_len_offset_);
    +
    +        // Start writing variable-length data at the beginning of the
    +        // newly allocated range.
    +        std::size_t current_variable_position = tuple_storage_bytes_ - header_->variable_length_bytes_allocated;
    +        std::uint32_t current_null_idx = 0;
    +        for (attribute_id accessor_attr_id = 0;
    +             static_cast<std::size_t >(accessor_attr_id) < insertInfo.num_attrs_;
++accessor_attr_id) {
    +          bool nullable = insertInfo.is_nullable_.getBit(accessor_attr_id);
    +          bool variable = insertInfo.is_variable_.getBit(accessor_attr_id);
    +
    +          if (!nullable && !variable) {
    +            DCHECK_EQ(-1, relation_.getNullableAttributeIndex(accessor_attr_id));
    +
    +            const void *attr_value = accessor->template getUntypedValue<false>(attribute_map[accessor_attr_id]);
    +            std::memcpy(fixed_length_attr_storage + insertInfo.fixed_len_offsets_[accessor_attr_id],
    +                        attr_value,
    +                        insertInfo.fixed_len_sizes_[accessor_attr_id]);
    +          } else if (nullable && !variable) {
    +            DCHECK_EQ(relation_.getNullableAttributeIndex(accessor_attr_id), static_cast<int>(current_null_idx));
    +
    +            TypedValue attr_value(accessor->getTypedValue(attribute_map[accessor_attr_id]));
    +            if (attr_value.isNull()) {
    +              tuple_null_bitmap.setBit(current_null_idx, true);
                 } else {
    -              const void *attr_value = accessor->template getUntypedValue<false>(*attr_map_it);
    -              std::memcpy(fixed_length_attr_storage
    -                              + relation_.getFixedLengthAttributeOffset(attr_it->getID()),
    -                          attr_value,
    -                          attr_it->getType().maximumByteLength());
    +              std::memcpy(fixed_length_attr_storage + insertInfo.fixed_len_offsets_[accessor_attr_id],
    +                          attr_value.getDataPtr(),
    +                          insertInfo.fixed_len_sizes_[accessor_attr_id]);
                 }
    -          }
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    -          }
    -        }
    -      }
    -    } else {
    -      if (relation_.isVariableLength()) {
    -        while (accessor->next()) {
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    -          const std::size_t tuple_variable_bytes
    -              = CalculateVariableSizeWithRemappedAttributes<decltype(*accessor), false>(
    -                  relation_, *accessor, attribute_map);
    -          if (!this->spaceToInsert(pos, tuple_variable_bytes)) {
    -            accessor->previous();
    -            break;
    -          }
    -          header_->variable_length_bytes_allocated += tuple_variable_bytes;
    -
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -          std::uint32_t *variable_length_info_array = reinterpret_cast<std::uint32_t*>(
    -              fixed_length_attr_storage + relation_.getFixedByteLength());
    -          std::uint32_t current_variable_position
    -              = tuple_storage_bytes_ - header_->variable_length_bytes_allocated;
    -
    -          std::vector<attribute_id>::const_iterator attr_map_it = attribute_map.begin();
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++attr_map_it) {
    -            const int variable_idx = relation_.getVariableLengthAttributeIndex(attr_it->getID());
    -            TypedValue attr_value(accessor->getTypedValue(*attr_map_it));
    -            if (variable_idx != -1) {
    -              const std::size_t attr_size = attr_value.getDataSize();
    -              variable_length_info_array[variable_idx << 1] = current_variable_position;
    -              variable_length_info_array[(variable_idx << 1) + 1] = attr_size;
    -              attr_value.copyInto(static_cast<char*>(tuple_storage_) + current_variable_position);
    -              current_variable_position += attr_size;
    +            current_null_idx++;
    +          } else if (!nullable && variable) {
    +            TypedValue attr_value(accessor->getTypedValue(attribute_map[accessor_attr_id]));
    +
    +            DCHECK_EQ(-1, relation_.getNullableAttributeIndex(accessor_attr_id));
    +            DCHECK_EQ(insertInfo.var_len_offsets_[accessor_attr_id],
    +                      relation_.getVariableLengthAttributeIndex(accessor_attr_id));
    +            DCHECK(!attr_value.isNull());
    +
    +            const std::size_t attr_size = attr_value.getDataSize();
    +            current_variable_position -= attr_size;
    +            const int var_len_info_idx = insertInfo.var_len_offsets_[accessor_attr_id]
* 2;
    +            variable_length_info_array[var_len_info_idx] = current_variable_position;
    +            variable_length_info_array[var_len_info_idx + 1] = attr_size;
    +            attr_value.copyInto(static_cast<char *>(tuple_storage_) + current_variable_position);
    +
    +            header_->variable_length_bytes_allocated += attr_size;
    +          } else {  // nullable, variable length
    +            DCHECK_EQ(static_cast<int>(current_null_idx), relation_.getNullableAttributeIndex(accessor_attr_id));
    +
    +            TypedValue attr_value(accessor->getTypedValue(attribute_map[accessor_attr_id]));
    +            if (attr_value.isNull()) {
    +              tuple_null_bitmap.setBit(current_null_idx, true);
                 } else {
    -              attr_value.copyInto(fixed_length_attr_storage
    -                                  + relation_.getFixedLengthAttributeOffset(attr_it->getID()));
    +              DCHECK_EQ(relation_.getVariableLengthAttributeIndex(accessor_attr_id),
    +                        insertInfo.var_len_offsets_[accessor_attr_id]);
    +
    +              const std::size_t attr_size = attr_value.getDataSize();
    +              current_variable_position -= attr_size;
    +              const int var_len_info_idx = insertInfo.var_len_offsets_[accessor_attr_id]
* 2;
    +              variable_length_info_array[var_len_info_idx] = current_variable_position;
    +              variable_length_info_array[var_len_info_idx + 1] = attr_size;
    +              attr_value.copyInto(static_cast<char *>(tuple_storage_) + current_variable_position);
    +              header_->variable_length_bytes_allocated += attr_size;
                 }
    -          }
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    +            current_null_idx++;
               }
             }
    -      } else {
    -        while (accessor->next()) {
    -          pos = this->isPacked() ? header_->num_tuples
    -                                 : occupancy_bitmap_->firstZero(pos);
    -          if (!this->spaceToInsert(pos, 0)) {
    -            accessor->previous();
    -            break;
    -          }
    -          void *tuple_slot = static_cast<char*>(tuple_storage_) + pos * tuple_slot_bytes_;
    -          char *fixed_length_attr_storage = static_cast<char*>(tuple_slot) + per_tuple_null_bitmap_bytes_;
    -
    -          std::vector<attribute_id>::const_iterator attr_map_it = attribute_map.begin();
    -          for (CatalogRelationSchema::const_iterator attr_it = relation_.begin();
    -               attr_it != relation_.end();
    -               ++attr_it, ++attr_map_it) {
    -            const void *attr_value = accessor->template getUntypedValue<false>(*attr_map_it);
    -            std::memcpy(fixed_length_attr_storage
    -                            + relation_.getFixedLengthAttributeOffset(attr_it->getID()),
    -                        attr_value,
    -                        attr_it->getType().maximumByteLength());
    -          }
    -          occupancy_bitmap_->setBit(pos, true);
    -          ++(header_->num_tuples);
    -          if (pos > header_->max_tid) {
    -            header_->max_tid = pos;
    -          }
    +        occupancy_bitmap_->setBit(pos, true);
    --- End diff --
    
    Agreed that it would be smaller in the common case (empty!) and since the 
    ```c++
      std::unique_ptr<BitVector<false>> occupancy_bitmap_;
    ```
    is on the heap anyways, it's not like we need to worry about how to serialize a variable
length list when a block is evicted.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

Mime
View raw message