Changeset 76825 in webkit
- Timestamp:
- Jan 27, 2011 11:58:33 AM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r76824 r76825 1 2011-01-19 Stephen White <senorblanco@chromium.org> 2 3 Reviewed by Darin Adler. 4 5 Fix performance regression in ImageQualityController::objectDestroyed(). 6 https://bugs.webkit.org/show_bug.cgi?id=52645 7 8 In r72282, I inadvertently introduced this regression by using a 9 linear search through the hash map on object destruction. This was 10 because the hash key consisted of both object pointer and layer id, 11 but on object destruction we only know the object pointer, requiring 12 a search to find all the layers. 13 By replacing the hash map with two nested hash maps, where the outer key 14 is the object and the inner key is the layer, we can find all the 15 relevant data for an object in one hash lookup. 16 17 * rendering/RenderBoxModelObject.cpp: 18 Replace the (object,layer)->size HashMap with object->layer and 19 layer->size HashMaps. 20 (WebCore::ImageQualityController::isEmpty): 21 Implement isEmpty() for the outer HashMap. 22 (WebCore::ImageQualityController::removeLayer): 23 When a layer is removed, remove it from the inner hash map. 24 (WebCore::ImageQualityController::set): 25 Implement set(): if the inner map exists, set the layer->size tuple 26 directly. If not, create a new inner map, set the tuple, and insert 27 it in the outer map. 28 (WebCore::ImageQualityController::objectDestroyed): 29 Look up the object in the outer map only. 30 (WebCore::ImageQualityController::highQualityRepaintTimerFired): 31 Cosmetic changes for the renamed now-outer hash map. 32 (WebCore::ImageQualityController::shouldPaintAtLowQuality): 33 Do both outer and inner hash map lookups. Call set() to add/update 34 entries to the hash maps. keyDestroyed() is now removeLayer(). 35 (WebCore::imageQualityController): 36 Make the ImageQualityController a file-static global, so it can be 37 created and destroyed on the fly. 38 (WebCore::RenderBoxModelObject::~RenderBoxModelObject): 39 If there is no ImageQualityController, don't call objectDestroyed(). 40 If it's empty, delete it. 41 42 1 43 2011-01-26 Enrica Casucci <enrica@apple.com> 2 44 -
trunk/Source/WebCore/rendering/RenderBoxModelObject.cpp
r76571 r76825 51 51 static const double cLowQualityTimeThreshold = 0.500; // 500 ms 52 52 53 typedef pair<RenderBoxModelObject*, const void*> LastPaintSizeMapKey;54 typedef HashMap< LastPaintSizeMapKey, IntSize> LastPaintSizeMap;53 typedef HashMap<const void*, IntSize> LayerSizeMap; 54 typedef HashMap<RenderBoxModelObject*, LayerSizeMap> ObjectLayerSizeMap; 55 55 56 56 // The HashMap for storing continuation pointers. … … 69 69 ImageQualityController(); 70 70 bool shouldPaintAtLowQuality(GraphicsContext*, RenderBoxModelObject*, Image*, const void* layer, const IntSize&); 71 void keyDestroyed(LastPaintSizeMapKey key); 71 void removeLayer(RenderBoxModelObject*, LayerSizeMap* innerMap, const void* layer); 72 void set(RenderBoxModelObject*, LayerSizeMap* innerMap, const void* layer, const IntSize&); 72 73 void objectDestroyed(RenderBoxModelObject*); 74 bool isEmpty() { return m_objectLayerSizeMap.isEmpty(); } 73 75 74 76 private: … … 76 78 void restartTimer(); 77 79 78 LastPaintSizeMap m_lastPaintSizeMap;80 ObjectLayerSizeMap m_objectLayerSizeMap; 79 81 Timer<ImageQualityController> m_timer; 80 82 bool m_animatedResizeIsActive; … … 87 89 } 88 90 89 void ImageQualityController::keyDestroyed(LastPaintSizeMapKey key) 90 { 91 m_lastPaintSizeMap.remove(key); 92 if (m_lastPaintSizeMap.isEmpty()) { 91 void ImageQualityController::removeLayer(RenderBoxModelObject* object, LayerSizeMap* innerMap, const void* layer) 92 { 93 if (innerMap) { 94 innerMap->remove(layer); 95 if (innerMap->isEmpty()) 96 objectDestroyed(object); 97 } 98 } 99 100 void ImageQualityController::set(RenderBoxModelObject* object, LayerSizeMap* innerMap, const void* layer, const IntSize& size) 101 { 102 if (innerMap) 103 innerMap->set(layer, size); 104 else { 105 LayerSizeMap newInnerMap; 106 newInnerMap.set(layer, size); 107 m_objectLayerSizeMap.set(object, newInnerMap); 108 } 109 } 110 111 void ImageQualityController::objectDestroyed(RenderBoxModelObject* object) 112 { 113 m_objectLayerSizeMap.remove(object); 114 if (m_objectLayerSizeMap.isEmpty()) { 93 115 m_animatedResizeIsActive = false; 94 116 m_timer.stop(); 95 117 } 96 118 } 97 98 void ImageQualityController::objectDestroyed(RenderBoxModelObject* object) 99 { 100 Vector<LastPaintSizeMapKey> keysToDie; 101 for (LastPaintSizeMap::iterator it = m_lastPaintSizeMap.begin(); it != m_lastPaintSizeMap.end(); ++it) 102 if (it->first.first == object) 103 keysToDie.append(it->first); 104 for (Vector<LastPaintSizeMapKey>::iterator it = keysToDie.begin(); it != keysToDie.end(); ++it) 105 keyDestroyed(*it); 106 } 107 119 108 120 void ImageQualityController::highQualityRepaintTimerFired(Timer<ImageQualityController>*) 109 121 { 110 122 if (m_animatedResizeIsActive) { 111 123 m_animatedResizeIsActive = false; 112 for ( LastPaintSizeMap::iterator it = m_lastPaintSizeMap.begin(); it != m_lastPaintSizeMap.end(); ++it)113 it->first .first->repaint();124 for (ObjectLayerSizeMap::iterator it = m_objectLayerSizeMap.begin(); it != m_objectLayerSizeMap.end(); ++it) 125 it->first->repaint(); 114 126 } 115 127 } … … 131 143 IntSize imageSize(image->width(), image->height()); 132 144 133 // Look ourselves up in the hashtable. 134 LastPaintSizeMapKey key(object, layer); 135 LastPaintSizeMap::iterator i = m_lastPaintSizeMap.find(key); 145 // Look ourselves up in the hashtables. 146 ObjectLayerSizeMap::iterator i = m_objectLayerSizeMap.find(object); 147 LayerSizeMap* innerMap = i != m_objectLayerSizeMap.end() ? &i->second : 0; 148 IntSize oldSize; 149 bool isFirstResize = true; 150 if (innerMap) { 151 LayerSizeMap::iterator j = innerMap->find(layer); 152 if (j != innerMap->end()) { 153 isFirstResize = false; 154 oldSize = j->second; 155 } 156 } 136 157 137 158 const AffineTransform& currentTransform = context->getCTM(); … … 139 160 if (!contextIsScaled && imageSize == size) { 140 161 // There is no scale in effect. If we had a scale in effect before, we can just remove this object from the list. 141 if (i != m_lastPaintSizeMap.end()) 142 m_lastPaintSizeMap.remove(key); 143 162 removeLayer(object, innerMap, layer); 144 163 return false; 145 164 } … … 151 170 return true; 152 171 } 172 153 173 // If an animated resize is active, paint in low quality and kick the timer ahead. 154 174 if (m_animatedResizeIsActive) { 155 m_lastPaintSizeMap.set(key, size);175 set(object, innerMap, layer, size); 156 176 restartTimer(); 157 177 return true; … … 160 180 // same as the last resize, draw at high res, but record the paint 161 181 // size and set the timer. 162 if (i == m_lastPaintSizeMap.end() || size == i->second) {182 if (isFirstResize || oldSize == size) { 163 183 restartTimer(); 164 m_lastPaintSizeMap.set(key, size);184 set(object, innerMap, layer, size); 165 185 return false; 166 186 } … … 168 188 // set the timer. 169 189 if (!m_timer.isActive()) { 170 keyDestroyed(key);190 removeLayer(object, innerMap, layer); 171 191 return false; 172 192 } … … 174 194 // is active, so draw at low quality, set the flag for animated resizes and 175 195 // the object to the list for high quality redraw. 176 m_lastPaintSizeMap.set(key, size);196 set(object, innerMap, layer, size); 177 197 m_animatedResizeIsActive = true; 178 198 restartTimer(); … … 180 200 } 181 201 202 static ImageQualityController* gImageQualityController = 0; 203 182 204 static ImageQualityController* imageQualityController() 183 205 { 184 static ImageQualityController* controller = new ImageQualityController; 185 return controller; 206 if (!gImageQualityController) 207 gImageQualityController = new ImageQualityController; 208 209 return gImageQualityController; 186 210 } 187 211 … … 224 248 ASSERT(!hasLayer()); 225 249 ASSERT(!m_layer); 226 imageQualityController()->objectDestroyed(this); 250 if (gImageQualityController) { 251 gImageQualityController->objectDestroyed(this); 252 if (gImageQualityController->isEmpty()) { 253 delete gImageQualityController; 254 gImageQualityController = 0; 255 } 256 } 227 257 } 228 258
Note: See TracChangeset
for help on using the changeset viewer.