ENH: refine resizing of zero-sized DynamicList/DynamicField

- since List is being used to manage the storage content for
  DynamicList, it needs to free old memory for zero-sized lists first.

  Consider this case (slightly exaggerated):

      line 0:  DynamicList<label> list;
      line 1:  list.reserve(100000);
      line 2:  list.reserve(200000);

  After line 0:
     - list has size=0, capacity=0 and data=nullptr

  After line 1:
     - list has size=0, capacity=1e+5 and data != nullptr

  After line 2:
     - list has size=0, capacity=2e+5 and data != nullptr

  ---

  The internal resizing associated with line 1 corresponds to what the
  List resize would naturally do. Namely allocate new storage, copy/move
  any overlapping elements (in this case none) before freeing the old
  storage and replacing with new storage.

  Applying the same resizing logic for line 2 means, however, that the
  old memory (1e5) and new memory (2e5) are temporarily both
  accessible - leading to an unnecessary memory peak.

  Now: if there is no overlap, just remove old memory first.
This commit is contained in:
Mark Olesen
2023-02-14 22:00:52 +01:00
parent 702225c249
commit a16f09b10c

View File

@ -46,12 +46,25 @@ void Foam::List<T>::doResize(const label len)
if (len > 0)
{
// With sign-check to avoid spurious -Walloc-size-larger-than
T* nv = new T[len];
const label overlap = min(this->size_, len);
if (overlap)
if (!overlap)
{
// Can discard old content before allocating new storage.
// - when used as storage for DynamicList, it is possible to have
// a zero-sized List with a non-null data pointer.
if (this->v_) delete[] this->v_;
this->size_ = len;
this->v_ = new T[len];
}
else
{
// Recover old (overlapping) content when resizing
T* nv = new T[len];
// ie, std::copy(this->v_, this->v_ + overlap, nv);
#ifdef USEMEMCPY
if (is_contiguous<T>::value)
{
@ -69,11 +82,11 @@ void Foam::List<T>::doResize(const label len)
nv[i] = std::move(vp[i]);
}
}
}
clear();
this->size_ = len;
this->v_ = nv;
delete[] this->v_;
this->size_ = len;
this->v_ = nv;
}
}
else
{