Title: [185663] trunk/Source/WTF
Revision
185663
Author
[email protected]
Date
2015-06-17 13:27:22 -0700 (Wed, 17 Jun 2015)

Log Message

SegmentedVector should waste less memory.
<https://webkit.org/b/146069>

Reviewed by Anders Carlsson.

We were wasting sizeof(Vector) on every segment in SegmentVector.
The segments were using inline capacity, and would never go beyond it,
so all the size/capacity/out-of-line-buffer metadata was useless.

Change the internal representation to Vector<T[SegmentSize]> instead.
This saves 16 bytes per segment, so lower SegmentSize -> bigger savings!

* wtf/SegmentedVector.h:
(WTF::SegmentedVectorIterator::operator*):
(WTF::SegmentedVectorIterator::operator->):
(WTF::SegmentedVectorIterator::operator++):
(WTF::SegmentedVectorIterator::operator==):
(WTF::SegmentedVectorIterator::operator!=):
(WTF::SegmentedVectorIterator::SegmentedVectorIterator):
(WTF::SegmentedVector::at):
(WTF::SegmentedVector::append):
(WTF::SegmentedVector::removeLast):
(WTF::SegmentedVector::grow):
(WTF::SegmentedVector::begin):
(WTF::SegmentedVector::end):
(WTF::SegmentedVector::deleteAllSegments):
(WTF::SegmentedVector::ensureSegmentsFor):
(WTF::SegmentedVector::ensureSegment):
(WTF::SegmentedVector::allocateSegment):
(WTF::SegmentedVectorIterator::operator=): Deleted.
(WTF::SegmentedVector::SegmentedVector): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (185662 => 185663)


--- trunk/Source/WTF/ChangeLog	2015-06-17 20:03:13 UTC (rev 185662)
+++ trunk/Source/WTF/ChangeLog	2015-06-17 20:27:22 UTC (rev 185663)
@@ -1,3 +1,37 @@
+2015-06-17  Andreas Kling  <[email protected]>
+
+        SegmentedVector should waste less memory.
+        <https://webkit.org/b/146069>
+
+        Reviewed by Anders Carlsson.
+
+        We were wasting sizeof(Vector) on every segment in SegmentVector.
+        The segments were using inline capacity, and would never go beyond it,
+        so all the size/capacity/out-of-line-buffer metadata was useless.
+
+        Change the internal representation to Vector<T[SegmentSize]> instead.
+        This saves 16 bytes per segment, so lower SegmentSize -> bigger savings!
+
+        * wtf/SegmentedVector.h:
+        (WTF::SegmentedVectorIterator::operator*):
+        (WTF::SegmentedVectorIterator::operator->):
+        (WTF::SegmentedVectorIterator::operator++):
+        (WTF::SegmentedVectorIterator::operator==):
+        (WTF::SegmentedVectorIterator::operator!=):
+        (WTF::SegmentedVectorIterator::SegmentedVectorIterator):
+        (WTF::SegmentedVector::at):
+        (WTF::SegmentedVector::append):
+        (WTF::SegmentedVector::removeLast):
+        (WTF::SegmentedVector::grow):
+        (WTF::SegmentedVector::begin):
+        (WTF::SegmentedVector::end):
+        (WTF::SegmentedVector::deleteAllSegments):
+        (WTF::SegmentedVector::ensureSegmentsFor):
+        (WTF::SegmentedVector::ensureSegment):
+        (WTF::SegmentedVector::allocateSegment):
+        (WTF::SegmentedVectorIterator::operator=): Deleted.
+        (WTF::SegmentedVector::SegmentedVector): Deleted.
+
 2015-06-16  Andreas Kling  <[email protected]>
 
         Remove unused template parameter InlineCapacity from SegmentedVector.

Modified: trunk/Source/WTF/wtf/SegmentedVector.h (185662 => 185663)


--- trunk/Source/WTF/wtf/SegmentedVector.h	2015-06-17 20:03:13 UTC (rev 185662)
+++ trunk/Source/WTF/wtf/SegmentedVector.h	2015-06-17 20:27:22 UTC (rev 185663)
@@ -44,56 +44,41 @@
 
         ~SegmentedVectorIterator() { }
 
-        T& operator*() const { return m_vector.m_segments.at(m_segment)->at(m_index); }
-        T* operator->() const { return &m_vector.m_segments.at(m_segment)->at(m_index); }
+        T& operator*() const { return m_vector.at(m_index); }
+        T* operator->() const { return &m_vector.at(m_index); }
 
         // Only prefix ++ operator supported
         Iterator& operator++()
         {
-            ASSERT(m_index != SegmentSize);
-            ++m_index;
-            if (m_index >= m_vector.m_segments.at(m_segment)->size())  {
-                if (m_segment + 1 < m_vector.m_segments.size()) {
-                    ASSERT(m_vector.m_segments.at(m_segment)->size() > 0);
-                    ++m_segment;
-                    m_index = 0;
-                } else {
-                    // Points to the "end" symbol
-                    m_segment = 0;
-                    m_index = SegmentSize;
-                }
-            }
+            m_index++;
             return *this;
         }
 
         bool operator==(const Iterator& other) const
         {
-            return m_index == other.m_index && m_segment == other.m_segment && &m_vector == &other.m_vector;
+            return m_index == other.m_index && &m_vector == &other.m_vector;
         }
 
         bool operator!=(const Iterator& other) const
         {
-            return m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector;
+            return m_index != other.m_index || &m_vector != &other.m_vector;
         }
 
         SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize>& other)
         {
             m_vector = other.m_vector;
-            m_segment = other.m_segment;
             m_index = other.m_index;
             return *this;
         }
 
     private:
-        SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t segment, size_t index)
+        SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t index)
             : m_vector(vector)
-            , m_segment(segment)
             , m_index(index)
         {
         }
 
         SegmentedVector<T, SegmentSize>& m_vector;
-        size_t m_segment;
         size_t m_index;
     };
 
@@ -110,10 +95,7 @@
     public:
         typedef SegmentedVectorIterator<T, SegmentSize> Iterator;
 
-        SegmentedVector()
-            : m_size(0)
-        {
-        }
+        SegmentedVector() = default;
 
         ~SegmentedVector()
         {
@@ -125,7 +107,8 @@
 
         T& at(size_t index)
         {
-            return segmentFor(index)->at(subscriptFor(index));
+            ASSERT_WITH_SECURITY_IMPLICATION(index < m_size);
+            return segmentFor(index)->entries[subscriptFor(index)];
         }
 
         const T& at(size_t index) const
@@ -151,10 +134,9 @@
         template <typename U> void append(U&& value)
         {
             ++m_size;
-
             if (!segmentExistsFor(m_size - 1))
-                m_segments.append(new Segment);
-            segmentFor(m_size - 1)->uncheckedAppend(std::forward<U>(value));
+                allocateSegment();
+            new (NotNull, &last()) T(std::forward<U>(value));
         }
 
         template<typename... Args>
@@ -166,7 +148,7 @@
 
         void removeLast()
         {
-            segmentFor(m_size - 1)->removeLast();
+            last().~T();
             --m_size;
         }
 
@@ -174,7 +156,10 @@
         {
             ASSERT(size > m_size);
             ensureSegmentsFor(size);
+            size_t oldSize = m_size;
             m_size = size;
+            for (size_t i = oldSize; i < m_size; ++i)
+                new (NotNull, &at(i)) T();
         }
 
         void clear()
@@ -186,12 +171,12 @@
 
         Iterator begin()
         {
-            return Iterator(*this, 0, m_size ? 0 : SegmentSize);
+            return Iterator(*this, 0);
         }
 
         Iterator end()
         {
-            return Iterator(*this, 0, SegmentSize);
+            return Iterator(*this, m_size);
         }
         
         void shrinkToFit()
@@ -200,12 +185,16 @@
         }
 
     private:
-        typedef Vector<T, SegmentSize> Segment;
+        struct Segment {
+            T entries[0];
+        };
 
         void deleteAllSegments()
         {
-            for (size_t i = 0; i < m_segments.size(); i++)
-                delete m_segments[i];
+            for (size_t i = 0; i < m_size; ++i)
+                at(i).~T();
+            for (size_t i = 0; i < m_segments.size(); ++i)
+                fastFree(m_segments[i]);
         }
 
         bool segmentExistsFor(size_t index)
@@ -228,24 +217,23 @@
             size_t segmentCount = (m_size + SegmentSize - 1) / SegmentSize;
             size_t neededSegmentCount = (size + SegmentSize - 1) / SegmentSize;
 
-            // Fill up to N - 1 segments.
-            size_t end = neededSegmentCount - 1;
-            for (size_t i = segmentCount ? segmentCount - 1 : 0; i < end; ++i)
-                ensureSegment(i, SegmentSize);
-
-            // Grow segment N to accomodate the remainder.
-            ensureSegment(end, subscriptFor(size - 1) + 1);
+            for (size_t i = segmentCount ? segmentCount - 1 : 0; i < neededSegmentCount; ++i)
+                ensureSegment(i);
         }
 
-        void ensureSegment(size_t segmentIndex, size_t size)
+        void ensureSegment(size_t segmentIndex)
         {
             ASSERT_WITH_SECURITY_IMPLICATION(segmentIndex <= m_segments.size());
             if (segmentIndex == m_segments.size())
-                m_segments.append(new Segment);
-            m_segments[segmentIndex]->grow(size);
+                allocateSegment();
         }
 
-        size_t m_size;
+        void allocateSegment()
+        {
+            m_segments.append(static_cast<Segment*>(fastMalloc(sizeof(T) * SegmentSize)));
+        }
+
+        size_t m_size { 0 };
         Vector<Segment*> m_segments;
     };
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to