| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "platform/text/CompressibleString.h" | |
| 6 | |
| 7 #include "platform/Histogram.h" | |
| 8 #include "wtf/Assertions.h" | |
| 9 #include "wtf/WTFThreadData.h" | |
| 10 #include "wtf/text/WTFString.h" | |
| 11 | |
| 12 namespace blink { | |
| 13 | |
| 14 class CompressibleStringTable { | |
| 15 WTF_MAKE_NONCOPYABLE(CompressibleStringTable); | |
| 16 public: | |
| 17 static CompressibleStringTable* create(WTFThreadData& data) | |
| 18 { | |
| 19 data.m_compressibleStringTable = new CompressibleStringTable; | |
| 20 data.m_compressibleStringTableDestructor = CompressibleStringTable::dest
roy; | |
| 21 return data.m_compressibleStringTable; | |
| 22 } | |
| 23 | |
| 24 void add(CompressibleStringImpl* string) | |
| 25 { | |
| 26 ASSERT(!m_table.contains(string)); | |
| 27 m_table.add(string); | |
| 28 } | |
| 29 | |
| 30 bool contains(CompressibleStringImpl* string) const | |
| 31 { | |
| 32 return m_table.contains(string); | |
| 33 } | |
| 34 | |
| 35 void remove(CompressibleStringImpl* string) | |
| 36 { | |
| 37 ASSERT(m_table.contains(string)); | |
| 38 m_table.remove(string); | |
| 39 } | |
| 40 | |
| 41 void compressAll() | |
| 42 { | |
| 43 HashSet<CompressibleStringImpl*>::iterator end = m_table.end(); | |
| 44 for (HashSet<CompressibleStringImpl*>::iterator iter = m_table.begin();
iter != end; ++iter) { | |
| 45 CompressibleStringImpl* string = *iter; | |
| 46 if (!string->isCompressed()) | |
| 47 string->compressString(); | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 private: | |
| 52 CompressibleStringTable() { } | |
| 53 | |
| 54 static void destroy(CompressibleStringTable* table) | |
| 55 { | |
| 56 delete table; | |
| 57 } | |
| 58 | |
| 59 HashSet<CompressibleStringImpl*> m_table; | |
| 60 }; | |
| 61 | |
| 62 static inline CompressibleStringTable& compressibleStringTable() | |
| 63 { | |
| 64 WTFThreadData& data = wtfThreadData(); | |
| 65 CompressibleStringTable* table = data.compressibleStringTable(); | |
| 66 if (UNLIKELY(!table)) | |
| 67 table = CompressibleStringTable::create(data); | |
| 68 return *table; | |
| 69 } | |
| 70 | |
| 71 static const unsigned CompressibleStringImplSizeThrehold = 100000; | |
| 72 | |
| 73 void CompressibleStringImpl::compressAll() | |
| 74 { | |
| 75 compressibleStringTable().compressAll(); | |
| 76 } | |
| 77 | |
| 78 CompressibleStringImpl::CompressibleStringImpl(PassRefPtr<StringImpl> impl) | |
| 79 : m_string(impl) | |
| 80 , m_isCompressed(false) | |
| 81 { | |
| 82 if (originalContentSizeInBytes() > CompressibleStringImplSizeThrehold) | |
| 83 compressibleStringTable().add(this); | |
| 84 } | |
| 85 | |
| 86 CompressibleStringImpl::~CompressibleStringImpl() | |
| 87 { | |
| 88 if (originalContentSizeInBytes() > CompressibleStringImplSizeThrehold) | |
| 89 compressibleStringTable().remove(this); | |
| 90 } | |
| 91 | |
| 92 enum CompressibleStringCountType { | |
| 93 StringWasCompressedInBackgroundTab, | |
| 94 StringWasDecompressed, | |
| 95 CompressibleStringCountTypeMax = StringWasDecompressed, | |
| 96 }; | |
| 97 | |
| 98 static void recordCompressibleStringCount(CompressibleStringCountType type) | |
| 99 { | |
| 100 DEFINE_THREAD_SAFE_STATIC_LOCAL(EnumerationHistogram, sringTypeHistogram, ne
w EnumerationHistogram("Memory.CompressibleStringCount", CompressibleStringCount
TypeMax + 1)); | |
| 101 sringTypeHistogram.count(type); | |
| 102 } | |
| 103 | |
| 104 // compressString does nothing but collect UMA so far. | |
| 105 // TODO(hajimehoshi): Implement this. | |
| 106 void CompressibleStringImpl::compressString() | |
| 107 { | |
| 108 recordCompressibleStringCount(StringWasCompressedInBackgroundTab); | |
| 109 ASSERT(!isCompressed()); | |
| 110 m_isCompressed = true; | |
| 111 } | |
| 112 | |
| 113 // decompressString does nothing but collect UMA so far. | |
| 114 // TODO(hajimehoshi): Implement this. | |
| 115 void CompressibleStringImpl::decompressString() | |
| 116 { | |
| 117 // TODO(hajimehoshi): We wanted to tell whether decompressing in a | |
| 118 // background tab or a foreground tab, but this was impossible. For example, | |
| 119 // one renderer process of a new tab page is used for multiple tabs. | |
| 120 // Another example is that reloading a page will re-use the process with a | |
| 121 // new Page object and updating a static variable along with reloading will | |
| 122 // be complex. See also crbug/581266. We will revisit when the situation | |
| 123 // changes. | |
| 124 recordCompressibleStringCount(StringWasDecompressed); | |
| 125 ASSERT(isCompressed()); | |
| 126 m_isCompressed = false; | |
| 127 } | |
| 128 | |
| 129 } // namespace blink | |
| OLD | NEW |