From 8617797a98993f47f2dec9610016a2ab653ff572 Mon Sep 17 00:00:00 2001 From: cxl Date: Sun, 10 Feb 2013 09:04:37 +0000 Subject: [PATCH] Core: InVector moved to Core, fixed MemoryProfile git-svn-id: svn://ultimatepp.org/upp/trunk@5780 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Core.h | 1 + uppsrc/Core/Core.upp | 2 + uppsrc/Core/InVector.h | 184 +++++++++++++ uppsrc/Core/InVector.hpp | 578 +++++++++++++++++++++++++++++++++++++++ uppsrc/Core/Vcont.cpp | 15 + uppsrc/Core/heaputil.cpp | 6 +- 6 files changed, 783 insertions(+), 3 deletions(-) create mode 100644 uppsrc/Core/InVector.h create mode 100644 uppsrc/Core/InVector.hpp diff --git a/uppsrc/Core/Core.h b/uppsrc/Core/Core.h index 901e8ce33..9dff92c85 100644 --- a/uppsrc/Core/Core.h +++ b/uppsrc/Core/Core.h @@ -278,6 +278,7 @@ class JsonIO; #include "BiCont.h" #include "Index.h" #include "Map.h" +#include "InVector.h" #include "Tuple.h" #include "Other.h" #include "Algo.h" diff --git a/uppsrc/Core/Core.upp b/uppsrc/Core/Core.upp index 86b7bf3a8..a2058e55b 100644 --- a/uppsrc/Core/Core.upp +++ b/uppsrc/Core/Core.upp @@ -84,6 +84,8 @@ file Index.h, Map.h, Index.hpp, + InVector.h, + InVector.hpp, Tuple.h, Other.h, Hash.cpp optimize_speed, diff --git a/uppsrc/Core/InVector.h b/uppsrc/Core/InVector.h new file mode 100644 index 000000000..de3ea0bb4 --- /dev/null +++ b/uppsrc/Core/InVector.h @@ -0,0 +1,184 @@ +template +class InVector : public MoveableAndDeepCopyOption< InVector > { +public: + class ConstIterator; + class Iterator; + +private: + Vector< Vector > data; + Vector< Vector > index; + int count; + int hcount; + int64 serial; + int blk_high; + int blk_low; + + void SetCache(int blki, int offset) const; + void ClearCache() const; + int FindBlock0(int& pos, int& off) const; + int FindBlock(int& pos, int& off) const; + int FindBlock(int& pos) const; + void Reindex(); + void SetBlkPar(); + + template + int FindUpperBound(const T& val, const L& less, int& off, int& pos); + + template + int FindLowerBound(const T& val, const L& less, int& off, int& pos); + + bool JoinSmall(int blki); + T *Insert0(int ii, int blki, int pos, int off, const T *val); + T *Insert0(int ii, const T *val); + + void Reset(); + + void SetIter(ConstIterator& it, int ii); + void SetBegin(ConstIterator& it); + void SetEnd(ConstIterator& it); + + void Chk() const { ASSERT_(!IsPicked(), "Broken pick semantics"); } + +public: + T& Insert(int i) { return *Insert0(i, NULL); } + T& Insert(int i, const T& x) { return *Insert0(i, &x); } + void InsertN(int i, int count); + void Remove(int i, int count = 1); + + const T& operator[](int i) const; + T& operator[](int i); + + T& Add() { return Insert(GetCount()); } + T& Add(const T& x) { return Insert(GetCount(), x); } + void AddN(int n) { Insert(GetCount(), n); } + + int GetCount() const { Chk(); return count; } + bool IsEmpty() const { return GetCount() == 0; } + + void Trim(int n) { Remove(GetCount() - n); } + void SetCount(int n); + void Clear(); + + T& At(int i) { if(i >= items) SetCount(i + 1); return (*this)[i]; } + + void Shrink(); + + void Set(int i, const T& x, int count); + T& Set(int i, const T& x) { Set(i, x, 1); return Get(i); } + + void Swap(int i1, int i2) { UPP::Swap((*this)[i1], (*this)[i2]); } + + void Drop(int n = 1) { ASSERT(n <= GetCount()); Trim(GetCount() - n); } + T& Top() { ASSERT(GetCount()); return (*this)[GetCount() - 1]; } + const T& Top() const { ASSERT(GetCount()); return (*this)[GetCount() - 1]; } + T Pop() { T h = Top(); Drop(); return h; } + + template + int FindUpperBound(const T& val, const L& less) { int off, pos; FindUpperBound(val, less, off, pos); return off + pos; } + int FindUpperBound(const T& val) { return FindUpperBound(val, StdLess()); } + + template + int FindLowerBound(const T& val, const L& less) { int off, pos; FindLowerBound(val, less, off, pos); return off + pos; } + int FindLowerBound(const T& val) { return FindLowerBound(val, StdLess()); } + + template int InsertUpperBound(const T& val, const L& less); + int InsertUpperBound(const T& val) { return InsertUpperBound(val, StdLess()); } + + template int Find(const T& val, const L& less); + int Find(const T& val) { return Find(val, StdLess()); } + + typedef T ValueType; + + ConstIterator Begin() const { ConstIterator it; SetBegin(it); return it; } + ConstIterator End() const { ConstIterator it; SetEnd(it); return it; } + ConstIterator GetIter(int pos) const { ConstIterator it; SetIter(it, pos); return it; } + + Iterator Begin() { Iterator it; SetBegin(it); return it; } + Iterator End() { Iterator it; SetEnd(it); return it; } + Iterator GetIter(int pos) { Iterator it; SetIter(it, pos); return it; } + + InVector(); + bool IsPicked() const { return data.IsPicked(); } + + InVector(const InVector& v, int); + + STL_VECTOR_COMPATIBILITY(InVector) + +#ifdef _DEBUG + void DumpIndex(); +#endif +}; + +template +class InVector::ConstIterator { + T *ptr; + T *begin; + T *end; + InVector *v; + int offset; + int blki; + + friend class InVector; + + void NextBlk(); + void PrevBlk(); + +public: + force_inline int GetIndex() const { return ptr - begin + offset; } + + force_inline ConstIterator& operator++() { ASSERT(ptr); if(++ptr == end) NextBlk(); return *this; } + force_inline ConstIterator& operator--() { ASSERT(ptr); if(ptr == begin) PrevBlk(); --ptr; return *this; } + force_inline ConstIterator operator++(int) { ConstIterator t = *this; ++*this; return t; } + force_inline ConstIterator operator--(int) { ConstIterator t = *this; --*this; return t; } + + force_inline ConstIterator& operator+=(int d); + ConstIterator& operator-=(int d) { return operator+=(-d); } + + ConstIterator operator+(int d) const { ConstIterator t = *this; t += d; return t; } + ConstIterator operator-(int d) const { return operator+(-d); } + + int operator-(const ConstIterator& x) const { return GetIndex() - x.GetIndex(); } + + bool operator==(const ConstIterator& b) const { return ptr == b.ptr; } + bool operator!=(const ConstIterator& b) const { return ptr != b.ptr; } + bool operator<(const ConstIterator& b) const { return blki == b.blki ? ptr < b.ptr : blki < b.blki; } + bool operator>(const ConstIterator& b) const { return blki == b.blki ? ptr > b.ptr : blki > b.blki; } + bool operator<=(const ConstIterator& b) const { return blki == b.blki ? ptr <= b.ptr : blki <= b.blki; } + bool operator>=(const ConstIterator& b) const { return blki == b.blki ? ptr >= b.ptr : blki >= b.blki; } + + operator bool() const { return ptr; } + + const T& operator*() const { return *ptr; } + const T *operator->() const { return ptr; } + const T& operator[](int i) const { ConstIterator h = *this; h += i; return *h; } +}; + +template +class InVector::Iterator : public InVector::ConstIterator { + typedef ConstIterator B; +public: + Iterator& operator++() { ConstIterator::operator++(); return *this; } + Iterator& operator--() { ConstIterator::operator--(); return *this; } + Iterator operator++(int) { Iterator t = *this; ++*this; return t; } + Iterator operator--(int) { Iterator t = *this; --*this; return t; } + + Iterator& operator+=(int d) { ConstIterator::operator+=(d); return *this; } + Iterator& operator-=(int d) { return operator+=(-d); } + + Iterator operator+(int d) const { Iterator t = *this; t += d; return t; } + Iterator operator-(int d) const { return operator+(-d); } + + int operator-(const Iterator& x) const { return B::GetIndex() - x.GetIndex(); } + + T& operator*() { return *B::ptr; } + T *operator->() { return B::ptr; } + T& operator[](int i) { Iterator h = *this; h += i; return *h; } + + const T& operator*() const { return *B::ptr; } + const T *operator->() const { return B::ptr; } + const T& operator[](int i) const { ConstIterator h = *this; h += i; return *h; } +}; + +#define LLOG(x) // DLOG(x) +#include "InVector.hpp" +#undef LLOG diff --git a/uppsrc/Core/InVector.hpp b/uppsrc/Core/InVector.hpp new file mode 100644 index 000000000..6ec800212 --- /dev/null +++ b/uppsrc/Core/InVector.hpp @@ -0,0 +1,578 @@ +int64 NewInVectorSerial(); + +template +InVector::InVector() +{ + serial = NewInVectorSerial(); + Reset(); +} + +template +void InVector::Reset() +{ + hcount = count = 0; + SetBlkPar(); +} + +template +void InVector::Clear() +{ + data.Clear(); + index.Clear(); + Reset(); +} + +extern thread__ int64 invector_cache_serial_; +extern thread__ int invector_cache_blki_; +extern thread__ int invector_cache_offset_; +extern thread__ int invector_cache_end_; + +template +force_inline void InVector::SetCache(int blki, int offset) const +{ + invector_cache_serial_ = serial; + invector_cache_blki_ = blki; + invector_cache_offset_ = offset; + invector_cache_end_ = offset + data[blki].GetCount(); +} + +template +force_inline void InVector::ClearCache() const +{ + invector_cache_serial_ = 0; +} + +template +force_inline int InVector::FindBlock(int& pos, int& off) const +{ + Chk(); + if(invector_cache_serial_ == serial && pos >= invector_cache_offset_ && + pos < invector_cache_end_) { + LLOG("Found in cache, serial: " << invector_cache_serial_ << ", offset: " << invector_cache_offset_ << ", end: " << invector_cache_end_); + off = invector_cache_offset_; + pos -= off; + return invector_cache_blki_; + } + return FindBlock0(pos, off); +} + +template +int InVector::FindBlock0(int& pos, int& off) const +{ + LLOG("FindBlock " << pos); + ASSERT(pos >= 0 && pos <= count); + if(pos == count) { + LLOG("Found last"); + pos = data.Top().GetCount(); + off = count - pos; + return data.GetCount() - 1; + } + int blki = 0; + int offset = 0; + for(int i = index.GetCount(); --i >= 0;) { + int n = index[i][blki]; + if(pos >= n) { + blki++; + pos -= n; + offset += n; + } + blki += blki; + } + int n = data[blki].GetCount(); + if(pos >= n) { + blki++; + pos -= n; + offset += n; + } + + SetCache(blki, offset); + + off = offset; + return blki; +} + +template +force_inline int InVector::FindBlock(int& pos) const +{ + int h; + return FindBlock(pos, h); +} + +template +const T& InVector::operator[](int i) const +{ + LLOG("operator[] " << i); + ASSERT(i >= 0 && i < count); + int blki = FindBlock(i); + return data[blki][i]; +} + +template +T& InVector::operator[](int i) +{ + LLOG("operator[] " << i); + ASSERT(i >= 0 && i < count); + int blki = FindBlock(i); + return data[blki][i]; +} + +template +void InVector::Reindex() +{ + LLOG("--- Reindexing"); + ClearCache(); + SetBlkPar(); + index.Clear(); + hcount = 0; + Vector *ds = data.Begin(); + Vector *dend = data.End(); + int n = data.GetCount(); + if(n <= 2) + return; + Vector& w = index.Add(); + hcount = 2; + w.SetCount((n + 1) >> 1); + int *t = w.Begin(); + while(ds != dend) { + *t = (ds++)->GetCount(); + if(ds == dend) + break; + *t++ += (ds++)->GetCount(); + } + int *s = w.Begin(); + int *end = w.End(); + n = w.GetCount(); + while(n > 2) { + Vector& w = index.Add(); + hcount += hcount; + w.SetCount((n + 1) >> 1); + t = w.Begin(); + while(s != end) { + *t = *s++; + if(s == end) + break; + *t++ += *s++; + } + s = w.Begin(); + end = w.End(); + n = w.GetCount(); + } +} + +template +void InVector::SetBlkPar() +{ +#if defined(_DEBUG) && defined(flagIVTEST) + blk_high = 11; + blk_low = 5; +#else + int n = 2500 + data.GetCount() / 4; + blk_high = max(n / (int)sizeof(T), 16); + blk_low = max(n / 3 / (int)sizeof(T), 16); +#endif +} + +template +T *InVector::Insert0(int ii, int blki, int pos, int off, const T *val) +{ + if(data[blki].GetCount() > blk_high) { + Vector& x = data.Insert(blki + 1); + x.InsertSplit(0, data[blki], data[blki].GetCount() / 2); + Reindex(); + pos = ii; + blki = FindBlock(pos, off); + } + LLOG("blki: " << blki << ", pos: " << pos); + count++; + int q = blki; + for(int i = 0; i < index.GetCount(); i++) + index[i].At(q >>= 1, 0)++; + if(val) + data[blki].Insert(pos, *val); + else + data[blki].Insert(pos); + SetCache(blki, off); + return &data[blki][pos]; +} + +template +force_inline bool InVector::JoinSmall(int blki) +{ + if(blki < data.GetCount()) { + int n = data[blki].GetCount(); + if(n == 0) { + data.Remove(blki); + return true; + } + if(n < blk_low) { + if(blki > 0 && data[blki - 1].GetCount() + n <= blk_high) { + data[blki - 1].AppendPick(data[blki]); + data.Remove(blki); + return true; + } + if(blki + 1 < data.GetCount() && n + data[blki + 1].GetCount() <= blk_high) { + data[blki].AppendPick(data[blki + 1]); + data.Remove(blki + 1); + return true; + } + } + } + return false; +} + +template +T *InVector::Insert0(int ii, const T *val) +{ + ASSERT(ii >= 0 && ii <= GetCount()); + if(data.GetCount() == 0) { + count++; + ClearCache(); + if(val) { + data.Add().Add(*val); + return &data[0][0]; + } + return &data.Add().Insert(0); + } + int pos = ii; + int off; + int blki = FindBlock(pos, off); + return Insert0(ii, blki, pos, off, val); +} + +template +void InVector::InsertN(int ii, int n) +{ + ASSERT(ii >= 0 && ii <= GetCount() && n >= 0); + + if(n == 0) + return; + + if(data.GetCount() == 0 && n > 0) { + count++; + data.Add().Add(); + if(--n == 0) + return; + } + + int pos = ii; + int off; + int blki = FindBlock(pos, off); + int bc = data[blki].GetCount(); + + count += n; + + if(bc + n < blk_high) { + data[blki].InsertN(pos, n); + int q = blki; + for(int i = 0; i < index.GetCount(); i++) + index[i].At(q >>= 1, 0) += n; + SetCache(blki, off); + } + else + if(bc - pos + n < blk_high) { + Vector& t = data.Insert(blki + 1); + t.InsertN(0, n); + t.InsertSplit(n, data[blki], pos); + data[blki].Shrink(); + Reindex(); + } + else { + int m = (blk_high + blk_low) / 2; + int bn = (n + m - 1) / m; + int ti; + if(pos) { + ti = blki + 1; + data.InsertN(ti, bn + 1); + data[ti + bn].InsertSplit(0, data[blki], pos); + data[blki].Shrink(); + } + else { + ti = blki; + data.InsertN(ti, bn); + } + for(int i = 0; i < bn; i++) { + int q = min(m, n); + data[ti + i].SetCount(q); + n -= q; + } + ASSERT(n == 0); + Reindex(); + } +} + +template +void InVector::Remove(int pos, int n) +{ + ASSERT(pos >= 0 && pos + n <= GetCount()); + count -= n; + int off; + int blki = FindBlock(pos, off); + if(pos + n < data[blki].GetCount()) { + data[blki].Remove(pos, n); + if(JoinSmall(blki)) + Reindex(); + else { + int q = blki; + for(int i = 0; i < index.GetCount(); i++) + index[i].At(q >>= 1, 0) -= n; + SetCache(blki, off); + } + } + else { + int b1 = blki; + int nn = min(n, data[b1].GetCount() - pos); + data[b1++].Remove(pos, nn); + n -= nn; + int b2 = b1; + while(n >= data[b2].GetCount()) { + n -= min(n, data[b2].GetCount()); + b2++; + } + data.Remove(b1, b2 - b1); + data[b1].Remove(0, n); + JoinSmall(blki + 1); + JoinSmall(blki); + Reindex(); + } +} + +template +void InVector::SetCount(int n) +{ + if(n < GetCount()) + Trim(n); + else + Insert(GetCount(), n - GetCount()); +} + +template +void InVector::Shrink() +{ + for(int i = 0; i < data.GetCount(); i++) + data[i].Shrink(); + data.Shrink(); + for(int i = 0; i < index.GetCount(); i++) + index[i].Shrink(); + index.Shrink(); +} + +template +void InVector::Set(int i, const T& x, int count) +{ + Iterator it = GetIter(i); + while(count-- > 0) + *it++ = x; +} + +template +InVector::InVector(const InVector& v, int) +{ + data <<= v.data; + index <<= v.index; + count = v.count; + hcount = v.hcount; + blk_high = v.blk_high; + blk_low = v.blk_low; + serial = NewInVectorSerial(); +} + +template +template +int InVector::FindUpperBound(const T& val, const L& less, int& off, int& pos) +{ + if(data.GetCount() == 0) { + pos = off = 0; + return 0; + } + int blki = 0; + int ii = 0; + int offset = 0; + int half = hcount; + for(int i = index.GetCount(); --i >= 0;) { + int m = blki + half; + if(m - 1 < data.GetCount() && !less(val, data[m - 1].Top())) { + blki = m; + offset += index[i][ii]; + ii++; + } + ii += ii; + half >>= 1; + } + if(blki < data.GetCount()) { + if(!less(val, data[blki].Top())) + offset += data[blki++].GetCount(); + if(blki < data.GetCount()) { + pos = Upp::FindUpperBound(data[blki], val, less); + off = offset; + SetCache(blki, offset); + return blki; + } + } + pos = data.Top().GetCount(); + off = count - pos; + blki--; + return blki; +} + +template +template +int InVector::FindLowerBound(const T& val, const L& less, int& off, int& pos) +{ + if(data.GetCount() == 0) { + pos = off = 0; + return 0; + } + int blki = 0; + int ii = 0; + int offset = 0; + int half = hcount; + for(int i = index.GetCount(); --i >= 0;) { + int m = blki + half; + if(m < data.GetCount() && less(data[m][0], val)) { + blki = m; + offset += index[i][ii]; + ii++; + } + ii += ii; + half >>= 1; + } + if(blki < data.GetCount()) { + if(blki + 1 < data.GetCount() && less(data[blki + 1][0], val)) + offset += data[blki++].GetCount(); + if(blki < data.GetCount()) { + pos = Upp::FindLowerBound(data[blki], val, less); + off = offset; + SetCache(blki, offset); + return blki; + } + } + pos = data.Top().GetCount(); + off = count - pos; + blki--; + return blki; +} + +template +template +int InVector::InsertUpperBound(const T& val, const L& less) +{ + if(data.GetCount() == 0) { + count++; + ClearCache(); + data.Add().Insert(0) = val; + return 0; + } + int off; + int pos; + int blki = FindUpperBound(val, less, off, pos); + Insert0(off + pos, blki, pos, off, &val); + return off + pos; +} + +template +template +int InVector::Find(const T& val, const L& less) +{ + int i = FindLowerBound(val, less); + return i < GetCount() && !less(val, (*this)[i]) ? i : -1; +} + + +template +void InVector::SetIter(ConstIterator& it, int ii) +{ + it.v = this; + it.blki = FindBlock(ii, it.offset); + it.begin = data[it.blki].Begin(); + it.end = data[it.blki].End(); + it.ptr = it.begin + ii; +} + +template +void InVector::SetBegin(ConstIterator& it) +{ + if(count) { + it.v = this; + it.blki = 0; + it.ptr = it.begin = data[0].Begin(); + it.end = data[0].End(); + it.offset = 0; + } + else + SetEnd(it); +} + +template +void InVector::SetEnd(ConstIterator& it) +{ + if(count) { + it.v = this; + it.blki = data.GetCount() - 1; + it.begin = data.Top().Begin(); + it.ptr = it.end = data.Top().End(); + it.offset = count - data.Top().GetCount(); + } + else { + it.v = this; + it.blki = 0; + it.ptr = it.begin = it.end = NULL; + it.offset = 0; + } +} + +template +force_inline typename InVector::ConstIterator& InVector::ConstIterator::operator+=(int d) +{ + if(d >= 0 ? d < end - ptr : -d < ptr - begin) + ptr += d; + else + v->SetIter(*this, GetIndex() + d); + ASSERT(end - begin == v->data[blki].GetCount()); + return *this; +} + +template +void InVector::ConstIterator::NextBlk() +{ + ASSERT(end - begin == v->data[blki].GetCount()); + if(blki + 1 < v->data.GetCount()) { + offset += v->data[blki].GetCount(); + ++blki; + ptr = begin = v->data[blki].Begin(); + end = v->data[blki].End(); + } +} + +template +void InVector::ConstIterator::PrevBlk() +{ + --blki; + begin = v->data[blki].Begin(); + ptr = end = v->data[blki].End(); + offset -= v->data[blki].GetCount(); +} + +#ifdef _DEBUG +template +void InVector::DumpIndex() +{ + String h; + DLOG("------- InVector dump, " << index.GetCount()); + for(int i = 0; i < data.GetCount(); i++) { + if(i) + h << ", "; + h << data[i].GetCount(); + } + DLOG(h); + for(int j = 0; j < index.GetCount(); j++) { + h.Clear(); + for(int k = 0; k < index[j].GetCount(); k++) { + if(k) + h << ", "; + h << index[j][k]; + } + DLOG(h); + } + DLOG("."); +} +#endif diff --git a/uppsrc/Core/Vcont.cpp b/uppsrc/Core/Vcont.cpp index cd67aa67b..181b9e67d 100644 --- a/uppsrc/Core/Vcont.cpp +++ b/uppsrc/Core/Vcont.cpp @@ -68,4 +68,19 @@ void VectorGrowF_(void *v_, int sizeofT) MemoryFree(prev); } + +int64 NewInVectorSerial() +{ + static int64 x; + INTERLOCKED { + ++x; + } + return x; +} + +thread__ int64 invector_cache_serial_; +thread__ int invector_cache_blki_; +thread__ int invector_cache_offset_; +thread__ int invector_cache_end_; + END_UPP_NAMESPACE diff --git a/uppsrc/Core/heaputil.cpp b/uppsrc/Core/heaputil.cpp index 7656f721e..974f77f04 100644 --- a/uppsrc/Core/heaputil.cpp +++ b/uppsrc/Core/heaputil.cpp @@ -200,7 +200,7 @@ void Heap::Make(MemoryProfile& f) size_t sz = ((BigHdr *)((byte *)m + BIGHDRSZ - sizeof(Header)))->size; f.large_count++; f.large_total += sz; - if(ii < 4096) + if(ii < 1024) f.large_size[ii++] = sz; m = m->next; } @@ -211,13 +211,13 @@ void Heap::Make(MemoryProfile& f) if(h->free) { f.large_free_count++; f.large_free_total += h->size; - if(fi < 4096) + if(fi < 1024) f.large_free_size[fi++] = h->size; } else { f.large_count++; f.large_total += h->size; - if(ii < 4096) + if(ii < 1024) f.large_size[ii++] = h->size; } h = h->Next();