- Revision
- 176115
- Author
- [email protected]
- Date
- 2014-11-13 20:26:45 -0800 (Thu, 13 Nov 2014)
Log Message
[mac] Keep around more decoded image data, since it's purgeable
https://bugs.webkit.org/show_bug.cgi?id=125273
<rdar://problem/13205438>
Reviewed by Simon Fraser.
No new tests, just an optimization.
Instead of throwing away decoded image data eagerly, allow the operating
system to manage the memory via the standard purgeability mechanism,
where it can.
This improves the performance on some pathological cases (extremely large
animated GIFs) by up to 8x.
* loader/cache/MemoryCache.cpp:
(WebCore::MemoryCache::pruneLiveResourcesToSize):
Don't prune live resources' decoded data if it is purgeable.
* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::destroyDecodedDataIfNecessary):
Don't eagerly throw away decoded image data if it's purgeable.
* loader/cache/CachedImage.h:
* loader/cache/CachedResource.h:
(WebCore::CachedResource::decodedDataIsPurgeable):
* platform/graphics/BitmapImage.h:
* platform/graphics/Image.h:
(WebCore::Image::decodedDataIsPurgeable):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (176114 => 176115)
--- trunk/Source/WebCore/ChangeLog 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/ChangeLog 2014-11-14 04:26:45 UTC (rev 176115)
@@ -1,3 +1,35 @@
+2014-11-13 Tim Horton <[email protected]>
+
+ [mac] Keep around more decoded image data, since it's purgeable
+ https://bugs.webkit.org/show_bug.cgi?id=125273
+ <rdar://problem/13205438>
+
+ Reviewed by Simon Fraser.
+
+ No new tests, just an optimization.
+
+ Instead of throwing away decoded image data eagerly, allow the operating
+ system to manage the memory via the standard purgeability mechanism,
+ where it can.
+
+ This improves the performance on some pathological cases (extremely large
+ animated GIFs) by up to 8x.
+
+ * loader/cache/MemoryCache.cpp:
+ (WebCore::MemoryCache::pruneLiveResourcesToSize):
+ Don't prune live resources' decoded data if it is purgeable.
+
+ * platform/graphics/BitmapImage.cpp:
+ (WebCore::BitmapImage::destroyDecodedDataIfNecessary):
+ Don't eagerly throw away decoded image data if it's purgeable.
+
+ * loader/cache/CachedImage.h:
+ * loader/cache/CachedResource.h:
+ (WebCore::CachedResource::decodedDataIsPurgeable):
+ * platform/graphics/BitmapImage.h:
+ * platform/graphics/Image.h:
+ (WebCore::Image::decodedDataIsPurgeable):
+
2014-11-13 Myles C. Maxfield <[email protected]>
Addressing post-review comment
Modified: trunk/Source/WebCore/loader/cache/CachedImage.h (176114 => 176115)
--- trunk/Source/WebCore/loader/cache/CachedImage.h 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/loader/cache/CachedImage.h 2014-11-14 04:26:45 UTC (rev 176115)
@@ -24,6 +24,7 @@
#define CachedImage_h
#include "CachedResource.h"
+#include "Image.h"
#include "ImageObserver.h"
#include "IntRect.h"
#include "IntSizeHash.h"
@@ -115,6 +116,8 @@
virtual bool stillNeedsLoad() const override { return !errorOccurred() && status() == Unknown && !isLoading(); }
+ virtual bool decodedDataIsPurgeable() const override { return m_image && m_image->decodedDataIsPurgeable(); }
+
// ImageObserver
virtual void decodedSizeChanged(const Image*, int delta) override;
virtual void didDraw(const Image*) override;
Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (176114 => 176115)
--- trunk/Source/WebCore/loader/cache/CachedResource.h 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h 2014-11-14 04:26:45 UTC (rev 176115)
@@ -144,6 +144,8 @@
unsigned encodedSize() const { return m_encodedSize; }
unsigned decodedSize() const { return m_decodedSize; }
unsigned overheadSize() const;
+
+ virtual bool decodedDataIsPurgeable() const { return false; }
bool isLoaded() const { return !m_loading; } // FIXME. Method name is inaccurate. Loading might not have started yet.
Modified: trunk/Source/WebCore/loader/cache/MemoryCache.cpp (176114 => 176115)
--- trunk/Source/WebCore/loader/cache/MemoryCache.cpp 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/loader/cache/MemoryCache.cpp 2014-11-14 04:26:45 UTC (rev 176115)
@@ -342,6 +342,11 @@
if (!shouldDestroyDecodedDataForAllLiveResources && elapsedTime < cMinDelayBeforeLiveDecodedPrune)
return;
+ if (current->decodedDataIsPurgeable()) {
+ current = prev;
+ continue;
+ }
+
// Destroy our decoded data. This will remove us from
// m_liveDecodedResources, and possibly move us to a different LRU
// list in m_allResources.
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (176114 => 176115)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp 2014-11-14 04:26:45 UTC (rev 176115)
@@ -132,6 +132,11 @@
const unsigned largeAnimationCutoff = 5242880;
#endif
+ // If decoded data is purgeable, the operating system will
+ // take care of throwing it away when the system is under pressure.
+ if (decodedDataIsPurgeable())
+ return;
+
// If we have decoded frames but there is no encoded data, we shouldn't destroy
// the decoded image since we won't be able to reconstruct it later.
if (!data() && m_frames.size())
Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.h (176114 => 176115)
--- trunk/Source/WebCore/platform/graphics/BitmapImage.h 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.h 2014-11-14 04:26:45 UTC (rev 176115)
@@ -283,6 +283,15 @@
#endif
private:
+ virtual bool decodedDataIsPurgeable() const override
+ {
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+ return true;
+#else
+ return false;
+#endif
+ }
+
ImageSource m_source;
mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
mutable IntSize m_sizeRespectingOrientation;
Modified: trunk/Source/WebCore/platform/graphics/Image.h (176114 => 176115)
--- trunk/Source/WebCore/platform/graphics/Image.h 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/platform/graphics/Image.h 2014-11-14 04:26:45 UTC (rev 176115)
@@ -114,6 +114,7 @@
virtual String filenameExtension() const { return String(); } // null string if unknown
virtual void destroyDecodedData(bool destroyAll = true) = 0;
+ virtual bool decodedDataIsPurgeable() const { return false; }
SharedBuffer* data() { return m_encodedImageData.get(); }
Modified: trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp (176114 => 176115)
--- trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp 2014-11-14 02:53:22 UTC (rev 176114)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp 2014-11-14 04:26:45 UTC (rev 176115)
@@ -50,6 +50,17 @@
const CFStringRef kCGImageSourceSubsampleFactor = CFSTR("kCGImageSourceSubsampleFactor");
#endif
+#if __has_include(<CoreGraphics/CGImagePrivate.h>)
+#import <CoreGraphics/CGImagePrivate.h>
+#else
+enum {
+ kCGImageCachingTransient = 1,
+ kCGImageCachingTemporary = 3
+};
+typedef uint32_t CGImageCachingFlags;
+extern "C" void CGImageSetCachingFlags(CGImageRef image, CGImageCachingFlags flags);
+#endif
+
namespace WebCore {
const CFStringRef WebCoreCGImagePropertyAPNGUnclampedDelayTime = CFSTR("UnclampedDelayTime");
@@ -343,7 +354,7 @@
CGImageRef ImageSource::createFrameAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
{
if (!initialized())
- return 0;
+ return nullptr;
RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(subsamplingLevel).get()));
@@ -364,8 +375,19 @@
CFStringRef imageUTI = CGImageSourceGetType(m_decoder);
static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
- if (!imageUTI || !CFEqual(imageUTI, xbmUTI))
+
+ if (!imageUTI)
return image.leakRef();
+
+#if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
+ if (CFEqual(imageUTI, kUTTypeGIF)) {
+ CGImageSetCachingFlags(image.get(), kCGImageCachingTransient);
+ return image.leakRef();
+ }
+#endif
+
+ if (!CFEqual(imageUTI, xbmUTI))
+ return image.leakRef();
// If it is an xbm image, mask out all the white areas to render them transparent.
const CGFloat maskingColors[6] = {255, 255, 255, 255, 255, 255};