Bug 125477 - Allow ImageBuffer to re-use IOSurfaces
Summary: Allow ImageBuffer to re-use IOSurfaces
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Myles C. Maxfield
URL:
Keywords:
Depends on: 126164
Blocks:
  Show dependency treegraph
 
Reported: 2013-12-09 17:12 PST by Myles C. Maxfield
Modified: 2015-08-26 23:51 PDT (History)
12 users (show)

See Also:


Attachments
Patch (32.42 KB, patch)
2013-12-09 18:25 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (32.77 KB, patch)
2013-12-10 13:09 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (35.74 KB, patch)
2013-12-11 12:21 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (33.67 KB, patch)
2013-12-11 16:21 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (33.81 KB, patch)
2013-12-11 17:04 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (46.70 KB, patch)
2013-12-11 23:11 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (46.92 KB, patch)
2013-12-12 00:54 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from webkit-ews-10 for mac-mountainlion-wk2 (457.25 KB, application/zip)
2013-12-12 01:57 PST, Build Bot
no flags Details
Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2 (460.53 KB, application/zip)
2013-12-12 02:55 PST, Build Bot
no flags Details
Archive of layout-test-results from webkit-ews-05 for mac-mountainlion (510.24 KB, application/zip)
2013-12-12 03:58 PST, Build Bot
no flags Details
Patch (47.00 KB, patch)
2013-12-13 17:45 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (27.45 KB, patch)
2013-12-19 00:18 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (28.10 KB, patch)
2013-12-19 15:49 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (31.15 KB, patch)
2013-12-19 18:54 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (28.93 KB, patch)
2013-12-19 22:40 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (29.24 KB, patch)
2013-12-20 14:09 PST, Myles C. Maxfield
ggaren: commit-queue-
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Myles C. Maxfield 2013-12-09 17:12:05 PST
Allow ImageBuffer to re-use IOSurfaces
Comment 1 Myles C. Maxfield 2013-12-09 18:25:00 PST
Created attachment 218818 [details]
Patch
Comment 2 WebKit Commit Bot 2013-12-09 18:27:46 PST
Attachment 218818 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast/canvas/canvas-backing-store-reuse-expected.txt', u'LayoutTests/fast/canvas/canvas-backing-store-reuse.html', u'PerformanceTests/Canvas/reuse.html', u'PerformanceTests/ChangeLog', u'Source/WebCore/ChangeLog', u'Source/WebCore/WebCore.xcodeproj/project.pbxproj', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h', u'Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp', '--commit-queue']" exit_code: 1
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:35:  Missing spaces around /  [whitespace/operators] [3]
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:113:  Comma should be at the beginning of the line in a member initialization list.  [whitespace/init] [4]
Total errors found: 2 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 3 Myles C. Maxfield 2013-12-09 18:27:58 PST
The style errors are caused by bugs in check-webkit-style. I will fix that script tomorrow.
Comment 4 Build Bot 2013-12-09 18:55:23 PST
Comment on attachment 218818 [details]
Patch

Attachment 218818 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/47338061
Comment 5 Build Bot 2013-12-09 19:41:31 PST
Comment on attachment 218818 [details]
Patch

Attachment 218818 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/47338068
Comment 6 Build Bot 2013-12-09 20:30:29 PST
Comment on attachment 218818 [details]
Patch

Attachment 218818 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/47268250
Comment 7 Tim Horton 2013-12-09 20:36:49 PST
Comment on attachment 218818 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=218818&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:128
> +        if (info.colorSpace == colorSpace) {

Comparing CGColorSpaceRefs by pointer value?!
Comment 8 Tim Horton 2013-12-09 20:49:17 PST
Comment on attachment 218818 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=218818&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:255
> +    CGContextClearRect(context, CGRectMake(0, 0, IOSurfaceGetWidth(ioSurface), IOSurfaceGetHeight(ioSurface)));

two calls to getwidth and getheight in this function.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:86
> +    ActiveIOSurfaceLookupMap m_activeIOSurfaces;

What's the point? I can't figure out the reason for keeping track of active surfaces.

> LayoutTests/fast/canvas/canvas-backing-store-reuse.html:14
> +  canvas.height = 100;

This test seems weird. The first canvas is smaller than the second one? Won't that mean that the second one necessarily never reuses the IOSurface from the first one?
What ensures that we've flushed before throwing away the first canvas? etc.
Comment 9 Myles C. Maxfield 2013-12-10 11:13:29 PST
Comment on attachment 218818 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=218818&action=review

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:128
>> +        if (info.colorSpace == colorSpace) {
> 
> Comparing CGColorSpaceRefs by pointer value?!

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:255
>> +    CGContextClearRect(context, CGRectMake(0, 0, IOSurfaceGetWidth(ioSurface), IOSurfaceGetHeight(ioSurface)));
> 
> two calls to getwidth and getheight in this function.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:86
>> +    ActiveIOSurfaceLookupMap m_activeIOSurfaces;
> 
> What's the point? I can't figure out the reason for keeping track of active surfaces.

To keep track of the CGContext and CGColorSpaceRef along with the IOSurface. I only want clients to have to hand back a single key, the IOSurfaceRef, so I have to have some way of looking up this other information from just this key. We need to remember what the color space to see if we're able to re-use it later.

>> LayoutTests/fast/canvas/canvas-backing-store-reuse.html:14
>> +  canvas.height = 100;
> 
> This test seems weird. The first canvas is smaller than the second one? Won't that mean that the second one necessarily never reuses the IOSurface from the first one?
> What ensures that we've flushed before throwing away the first canvas? etc.

Not at all - ImageBuffers can use larger-than-necessary IOSurfaces since r160121, and will do so if we find a cached IOSurface that is greater than the size we're looking for. However, a client can specify that they are only willing to accept a perfectly sized IOSurface using the needExactSize argument to ImageBufferBackingStoreCache::getIOSurface().

Flushing itself shouldn't be necessary; instead I clear the entire IOSurface in ImageBufferBackingStoreCache::releaseIOSurface().
Comment 10 Myles C. Maxfield 2013-12-10 13:08:20 PST
Style fixes are in https://bugs.webkit.org/show_bug.cgi?id=125534 and https://bugs.webkit.org/show_bug.cgi?id=125537
Comment 11 Myles C. Maxfield 2013-12-10 13:09:49 PST
Created attachment 218899 [details]
Patch
Comment 12 WebKit Commit Bot 2013-12-10 13:12:23 PST
Attachment 218899 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast/canvas/canvas-backing-store-reuse-expected.txt', u'LayoutTests/fast/canvas/canvas-backing-store-reuse.html', u'PerformanceTests/Canvas/reuse.html', u'PerformanceTests/ChangeLog', u'Source/WebCore/ChangeLog', u'Source/WebCore/WebCore.xcodeproj/project.pbxproj', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h', u'Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp', '--commit-queue']" exit_code: 1
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:42:  Missing spaces around /  [whitespace/operators] [3]
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:119:  Comma should be at the beginning of the line in a member initialization list.  [whitespace/init] [4]
Total errors found: 2 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 13 Build Bot 2013-12-10 13:35:57 PST
Comment on attachment 218899 [details]
Patch

Attachment 218899 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/47258294
Comment 14 Build Bot 2013-12-10 13:41:28 PST
Comment on attachment 218899 [details]
Patch

Attachment 218899 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/47688023
Comment 15 Sam Weinig 2013-12-10 13:56:57 PST
Comment on attachment 218899 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=218899&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:70
> +    typedef std::unordered_map<IOSurfaceRef, InternalIOSurfaceInfo> ActiveIOSurfaceLookupMap;
> +    typedef std::unordered_map<IOSurfaceRef, CachedIOSurfaceInfo> CachedIOSurfaceLookupMap;
> +    typedef std::multimap<int, CachedIOSurfaceLookupMap::iterator> DimensionalIOSurfaceLookupMap;

We tend to not use standard library containers.  Please convert to using WTF versions.
Comment 16 Myles C. Maxfield 2013-12-10 18:43:12 PST
Comment on attachment 218899 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=218899&action=review

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:70
>> +    typedef std::multimap<int, CachedIOSurfaceLookupMap::iterator> DimensionalIOSurfaceLookupMap;
> 
> We tend to not use standard library containers.  Please convert to using WTF versions.

I can't do that for a couple reasons:
1) I need a multimap which is ordered, because I iterate over the keys and I expect them to be in order when I do so. If we had an ordered map I could use a map of vectors to approximate a multimap; however, it appears that we don't have any sort of ordered data structure other than a vector (which is a no-go due to the runtime of insertion and removal)
2) I can't even use WTF::HashMap for the unordered_map here because this patch requires the ability to have multiple iterators pointing inside the same map, which WTF::HashTable doesn't allow. Indeed, HashTable::add() calls invalidateIterators() explicitly (HashTable.h:801)

I should, however, be able to make my CandidateMap a HashMap.
Comment 17 Myles C. Maxfield 2013-12-11 12:21:43 PST
Created attachment 218995 [details]
Patch
Comment 18 WebKit Commit Bot 2013-12-11 12:23:20 PST
Attachment 218995 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast/canvas/canvas-backing-store-reuse-expected.txt', u'LayoutTests/fast/canvas/canvas-backing-store-reuse.html', u'PerformanceTests/Canvas/reuse.html', u'PerformanceTests/ChangeLog', u'Source/WebCore/ChangeLog', u'Source/WebCore/WebCore.xcodeproj/project.pbxproj', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h', u'Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp', '--commit-queue']" exit_code: 1
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:42:  Missing spaces around /  [whitespace/operators] [3]
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:119:  Comma should be at the beginning of the line in a member initialization list.  [whitespace/init] [4]
Total errors found: 2 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 19 Build Bot 2013-12-11 12:30:46 PST
Comment on attachment 218995 [details]
Patch

Attachment 218995 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/48108008
Comment 20 Myles C. Maxfield 2013-12-11 12:39:35 PST
Looks like the Mac bots are still on 10.8, and the Purgeable calls I'm making are in 10.9 only
Comment 21 Build Bot 2013-12-11 12:58:10 PST
Comment on attachment 218995 [details]
Patch

Attachment 218995 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/48138014
Comment 22 Myles C. Maxfield 2013-12-11 16:21:12 PST
Created attachment 219012 [details]
Patch
Comment 23 WebKit Commit Bot 2013-12-11 16:23:28 PST
Attachment 219012 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast/canvas/canvas-backing-store-reuse-expected.txt', u'LayoutTests/fast/canvas/canvas-backing-store-reuse.html', u'PerformanceTests/Canvas/reuse.html', u'PerformanceTests/ChangeLog', u'Source/WebCore/ChangeLog', u'Source/WebCore/WebCore.xcodeproj/project.pbxproj', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h', u'Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp', '--commit-queue']" exit_code: 1
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:43:  Missing spaces around /  [whitespace/operators] [3]
Total errors found: 1 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 24 Myles C. Maxfield 2013-12-11 16:49:01 PST
Comment on attachment 218899 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=218899&action=review

>>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:70
>>> +    typedef std::multimap<int, CachedIOSurfaceLookupMap::iterator> DimensionalIOSurfaceLookupMap;
>> 
>> We tend to not use standard library containers.  Please convert to using WTF versions.
> 
> I can't do that for a couple reasons:
> 1) I need a multimap which is ordered, because I iterate over the keys and I expect them to be in order when I do so. If we had an ordered map I could use a map of vectors to approximate a multimap; however, it appears that we don't have any sort of ordered data structure other than a vector (which is a no-go due to the runtime of insertion and removal)
> 2) I can't even use WTF::HashMap for the unordered_map here because this patch requires the ability to have multiple iterators pointing inside the same map, which WTF::HashTable doesn't allow. Indeed, HashTable::add() calls invalidateIterators() explicitly (HashTable.h:801)
> 
> I should, however, be able to make my CandidateMap a HashMap.

***requires the ability to have persistent iterators
Comment 25 Build Bot 2013-12-11 16:53:06 PST
Comment on attachment 219012 [details]
Patch

Attachment 219012 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/48158076
Comment 26 Myles C. Maxfield 2013-12-11 17:04:46 PST
Created attachment 219018 [details]
Patch
Comment 27 WebKit Commit Bot 2013-12-11 17:06:20 PST
Attachment 219018 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast/canvas/canvas-backing-store-reuse-expected.txt', u'LayoutTests/fast/canvas/canvas-backing-store-reuse.html', u'PerformanceTests/Canvas/reuse.html', u'PerformanceTests/ChangeLog', u'Source/WebCore/ChangeLog', u'Source/WebCore/WebCore.xcodeproj/project.pbxproj', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h', u'Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp', '--commit-queue']" exit_code: 1
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:44:  Missing spaces around /  [whitespace/operators] [3]
Total errors found: 1 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 28 Build Bot 2013-12-11 17:15:13 PST
Comment on attachment 219018 [details]
Patch

Attachment 219018 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/47008224
Comment 29 Build Bot 2013-12-11 17:37:14 PST
Comment on attachment 219018 [details]
Patch

Attachment 219018 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/48108100
Comment 30 Myles C. Maxfield 2013-12-11 23:11:51 PST
Created attachment 219045 [details]
Patch
Comment 31 Build Bot 2013-12-11 23:43:45 PST
Comment on attachment 219045 [details]
Patch

Attachment 219045 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/47318215
Comment 32 Build Bot 2013-12-12 00:18:18 PST
Comment on attachment 219045 [details]
Patch

Attachment 219045 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/45068235
Comment 33 Myles C. Maxfield 2013-12-12 00:54:05 PST
Created attachment 219054 [details]
Patch
Comment 34 Build Bot 2013-12-12 01:57:17 PST
Comment on attachment 219054 [details]
Patch

Attachment 219054 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/48108228

New failing tests:
fast/canvas/2d.fillText.gradient.html
Comment 35 Build Bot 2013-12-12 01:57:19 PST
Created attachment 219060 [details]
Archive of layout-test-results from webkit-ews-10 for mac-mountainlion-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: webkit-ews-10  Port: mac-mountainlion-wk2  Platform: Mac OS X 10.8.5
Comment 36 Build Bot 2013-12-12 02:55:16 PST
Comment on attachment 219054 [details]
Patch

Attachment 219054 [details] did not pass mac-wk2-ews (mac-wk2):
Output: http://webkit-queues.appspot.com/results/48168085

New failing tests:
fast/canvas/2d.fillText.gradient.html
Comment 37 Build Bot 2013-12-12 02:55:19 PST
Created attachment 219066 [details]
Archive of layout-test-results from webkit-ews-14 for mac-mountainlion-wk2

The attached test failures were seen while running run-webkit-tests on the mac-wk2-ews.
Bot: webkit-ews-14  Port: mac-mountainlion-wk2  Platform: Mac OS X 10.8.5
Comment 38 Build Bot 2013-12-12 03:58:21 PST
Comment on attachment 219054 [details]
Patch

Attachment 219054 [details] did not pass mac-ews (mac):
Output: http://webkit-queues.appspot.com/results/45068302

New failing tests:
fast/canvas/2d.fillText.gradient.html
Comment 39 Build Bot 2013-12-12 03:58:24 PST
Created attachment 219071 [details]
Archive of layout-test-results from webkit-ews-05 for mac-mountainlion

The attached test failures were seen while running run-webkit-tests on the mac-ews.
Bot: webkit-ews-05  Port: mac-mountainlion  Platform: Mac OS X 10.8.5
Comment 40 Myles C. Maxfield 2013-12-13 17:45:12 PST
Created attachment 219213 [details]
Patch
Comment 41 Myles C. Maxfield 2013-12-16 20:01:10 PST
Breaking out the multimap piece into https://bugs.webkit.org/show_bug.cgi?id=125827
Comment 42 Geoffrey Garen 2013-12-17 11:08:16 PST
Comment on attachment 219213 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219213&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:236
> +    while (xIterator != m_xDimensionLookupMap.end() || yIterator != m_yDimensionLookupMap.end()) {
> +        ret = findIOSurfaceInfoHelper<0>(xIterator, m_xDimensionLookupMap, candidates, size, colorSpace, needExactSize);
> +        if (ret.success && (bestEver.iter == m_cachedIOSurfaces.end()
> +            || betterSurface(size, ret.iter->value, bestEver.iter->value, stopSearching)))
> +            bestEver = ret;
> +        if (stopSearching)
> +            break;
> +        ret = findIOSurfaceInfoHelper<1>(yIterator, m_yDimensionLookupMap, candidates, size, colorSpace, needExactSize);
> +        if (ret.success && (bestEver.iter == m_cachedIOSurfaces.end()
> +            || betterSurface(size, ret.iter->value, bestEver.iter->value, stopSearching)))
> +            bestEver = ret;
> +        if (stopSearching)
> +            break;
> +    }

If we have lots of surfaces with the same width and/or height, this code is O(N). That case seems likely to me. I don't think this much complexity is justified just to achieve O(N).
Comment 43 Geoffrey Garen 2013-12-17 11:22:27 PST
How many IOSurfaces do you plan to cache?

(1) If the answer is < 50, then I suggest a simple vector or doubly-linked list with linear search.

The Big-O complexity of linear search is just as good as the algorithm you've posted here, and the code complexity is about ten orders of magnitude lower -- which is, if you do the math, an order of orders of magnitude.

I believe you can do this in about 10 lines of code.

(2) If the answer is >= 50, then I suggest the following:

(1) Create a hash table in which the key is an area (width x height), rounded down to the nearest power of two (which is a simple mask instruction), and the value is a deque.

(2) Lookup should select a deque, and iterate end to start (LIFO order), to find an appropriate candidate. The common case will take the very last item, which is both the last item inserted and therefore cache-local, and also constant-time to remove.

(3) Insertion should select a deque and add to the end. If the deque exceeds a fixed limit in size, insertion should also remove from the beginning of the deque (FIFO order).

I believe you can do this in about 20 lines of code.
Comment 44 Myles C. Maxfield 2013-12-19 00:18:11 PST
Created attachment 219628 [details]
Patch
Comment 45 Myles C. Maxfield 2013-12-19 00:18:56 PST
I'll fix check-webkit-style tomorrow regarding the style errors.
Comment 46 WebKit Commit Bot 2013-12-19 00:19:47 PST
Attachment 219628 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast/canvas/canvas-backing-store-reuse-expected.txt', u'LayoutTests/fast/canvas/canvas-backing-store-reuse.html', u'PerformanceTests/Canvas/reuse.html', u'PerformanceTests/ChangeLog', u'Source/WebCore/ChangeLog', u'Source/WebCore/WebCore.xcodeproj/project.pbxproj', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h', u'Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp', '--commit-queue']" exit_code: 1
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:109:  This { should be at the end of the previous line  [whitespace/braces] [4]
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:72:  Missing spaces around &&  [whitespace/operators] [3]
Total errors found: 2 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 47 mitz 2013-12-19 00:36:57 PST
Comment on attachment 219628 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219628&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:23
> + * Copyright (C) 2013 Apple, Inc.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
> + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
> + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 

This is not the right copyright and license header.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:24
> + * Copyright (C) 2013 Apple, Inc.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
> + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
> + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
> + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
> + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
> + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
> + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
> + */

This is not the right copyright and license header.
Comment 48 Geoffrey Garen 2013-12-19 09:17:10 PST
Comment on attachment 219628 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219628&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:36
> +static const double purgeIntervalInMS = 30000;

This would make more sense specified in seconds.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:98
> +    IntSize actualSize = IntSize(IOSurfaceGetWidth(surface), IOSurfaceGetHeight(surface));

No need for "= IntSize" in this declaration.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:167
> +    InternalIOSurfaceInfo* toAdd = new InternalIOSurfaceInfo(lookup->value);

Manual new/delete is the enemy. You are aiding the enemy.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:168
> +    auto insertedTuple = m_cachedSurfaces.add(convertSizeToKey(surfaceSize), InfoLinkedList());

Should there be a limit on this cache? What happens if I allocate and free lots of canvases in a loop, all with different sizes?

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:69
> +    class InternalIOSurfaceInfo : public DoublyLinkedListNode<InternalIOSurfaceInfo> {

"internal" doesn't really mean anything. Think about what's different between this and IOSurfaceInfo, and put that in the name.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:88
> +    typedef HashMap<IOSurfaceRef, InternalIOSurfaceInfo> ActiveSurfaceMap;

Why is it OK for this to be a raw pointer? Who owns the IOSurfaceRef? I couldn't tell just by skimming the code.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:95
> +        return std::make_pair((size.width() + 7) & ~0x7, (size.height() + 7) & ~0x7);

Please use WTF::roundUpToMultipleOf.
Comment 49 Myles C. Maxfield 2013-12-19 10:52:46 PST
Comment on attachment 219628 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219628&action=review

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:23
>> + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
> 
> This is not the right copyright and license header.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:36
>> +static const double purgeIntervalInMS = 30000;
> 
> This would make more sense specified in seconds.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:98
>> +    IntSize actualSize = IntSize(IOSurfaceGetWidth(surface), IOSurfaceGetHeight(surface));
> 
> No need for "= IntSize" in this declaration.

This is a holdover from when I was working on Chrome (I got yelled at for not using the assignment operator). Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:167
>> +    InternalIOSurfaceInfo* toAdd = new InternalIOSurfaceInfo(lookup->value);
> 
> Manual new/delete is the enemy. You are aiding the enemy.

Is there a way to use DoublyLinkedListNode<> without manual new + delete? I'm trying to not invent a data structure

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:168
>> +    auto insertedTuple = m_cachedSurfaces.add(convertSizeToKey(surfaceSize), InfoLinkedList());
> 
> Should there be a limit on this cache? What happens if I allocate and free lots of canvases in a loop, all with different sizes?

Straightforward enough. Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:24
>> + */
> 
> This is not the right copyright and license header.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:69
>> +    class InternalIOSurfaceInfo : public DoublyLinkedListNode<InternalIOSurfaceInfo> {
> 
> "internal" doesn't really mean anything. Think about what's different between this and IOSurfaceInfo, and put that in the name.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:88
>> +    typedef HashMap<IOSurfaceRef, InternalIOSurfaceInfo> ActiveSurfaceMap;
> 
> Why is it OK for this to be a raw pointer? Who owns the IOSurfaceRef? I couldn't tell just by skimming the code.

The pointer is retained inside the InternalIOSurfaceInfo (soon to be IOSurfaceInfoWithCreationParams) which is the value type of the map. Originally I didn't think that I could make a map keyed off of a RetainPtr, but it looks like I can. I'll do that.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:95
>> +        return std::make_pair((size.width() + 7) & ~0x7, (size.height() + 7) & ~0x7);
> 
> Please use WTF::roundUpToMultipleOf.

Done.
Comment 50 Myles C. Maxfield 2013-12-19 15:49:58 PST
Created attachment 219693 [details]
Patch
Comment 51 Geoffrey Garen 2013-12-19 16:58:55 PST
Comment on attachment 219693 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219693&action=review

What I would suggest for eviction:

(1) If new item bigger than cache, do not cache it.

(2) while cache size + new item > limit, evict oldest item in current list.

This is good because old items of similar size, which did not match our query, are probably slightly too small or in the wrong color space.

(3) while cache size + new item > limit, for each bucket, while cache size + new item > limit, evict oldest item in bucket.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:51
> +    const void* keys[6];

Let's pull out the 6 here and make it a local constant.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:106
> +auto ImageBufferBackingStoreCache::findAcceptableCachedSurface(const IntSize& size, CGColorSpaceModel colorSpace, bool needExactSize) -> IOSurfaceInfoWithCreationParams*

Let's make this return a reference to the list plus a pointer.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:115
> +            ll.remove(info);
> +            return info;

Let's factor this into a helper function to do the memory management.

Empty lists also need to be removed from the cache table. Perhaps you can factor this into the helper function.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:129
> +        IntSize surfaceSize = IntSize(IOSurfaceGetWidth(surface), IOSurfaceGetHeight(surface));

"= IntSize".

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:133
> +        delete foundPtr;

Helper function to do memory management.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:163
> +        m_activeSurfaces.remove(lookup);

Let's remove old items instead of the new item. Otherwise, the cache will fill up with garbage and stay that way.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:176
> +    auto* toAdd = new IOSurfaceInfoWithCreationParams(lookup->value);
> +    auto insertedTuple = m_cachedSurfaces.add(convertSizeToKey(surfaceSize), InfoLinkedList());
> +    insertedTuple.iterator->value.append(toAdd);

Let's use a helper here too, to which we pass a list reference and lookup->value.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:188
> +            delete ll.removeHead();

Helper function to do memory management.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:198
> +    static const double purgeInterval = 30;

Since the current version of the cache does not make surfaces volatile, and they are wired memory, let's reduce this number to 5s. It can go back up when we do the volatile thing, since we won't monopolize wired memory then.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:50
> +        }

Need a newline after this function.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:107
> +    int pixelsCached;

Please use the "m_" prefix.
Comment 52 Myles C. Maxfield 2013-12-19 17:41:40 PST
Comment on attachment 219693 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219693&action=review

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:51
>> +    const void* keys[6];
> 
> Let's pull out the 6 here and make it a local constant.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:106
>> +auto ImageBufferBackingStoreCache::findAcceptableCachedSurface(const IntSize& size, CGColorSpaceModel colorSpace, bool needExactSize) -> IOSurfaceInfoWithCreationParams*
> 
> Let's make this return a reference to the list plus a pointer.

Instead, I'll make this function call the deletion helper directly, instead of passing the arguments to the deletion helper to getIOSurface() so getIOSurface() can call the deletion helper.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:115
>> +            return info;
> 
> Let's factor this into a helper function to do the memory management.
> 
> Empty lists also need to be removed from the cache table. Perhaps you can factor this into the helper function.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:129
>> +        IntSize surfaceSize = IntSize(IOSurfaceGetWidth(surface), IOSurfaceGetHeight(surface));
> 
> "= IntSize".

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:133
>> +        delete foundPtr;
> 
> Helper function to do memory management.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:163
>> +        m_activeSurfaces.remove(lookup);
> 
> Let's remove old items instead of the new item. Otherwise, the cache will fill up with garbage and stay that way.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:176
>> +    insertedTuple.iterator->value.append(toAdd);
> 
> Let's use a helper here too, to which we pass a list reference and lookup->value.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:188
>> +            delete ll.removeHead();
> 
> Helper function to do memory management.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:198
>> +    static const double purgeInterval = 30;
> 
> Since the current version of the cache does not make surfaces volatile, and they are wired memory, let's reduce this number to 5s. It can go back up when we do the volatile thing, since we won't monopolize wired memory then.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:50
>> +        }
> 
> Need a newline after this function.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:107
>> +    int pixelsCached;
> 
> Please use the "m_" prefix.

Done.
Comment 53 Geoffrey Garen 2013-12-19 17:54:07 PST
Comment on attachment 219693 [details]
Patch

Getting this old patch out of the queue.
Comment 54 Myles C. Maxfield 2013-12-19 18:54:45 PST
Created attachment 219712 [details]
Patch
Comment 55 Myles C. Maxfield 2013-12-19 18:55:45 PST
Style is a false negative. Will make a subsequent patch to address.
Comment 56 WebKit Commit Bot 2013-12-19 18:56:51 PST
Attachment 219712 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'LayoutTests/ChangeLog', u'LayoutTests/fast/canvas/canvas-backing-store-reuse-expected.txt', u'LayoutTests/fast/canvas/canvas-backing-store-reuse.html', u'PerformanceTests/Canvas/reuse.html', u'PerformanceTests/ChangeLog', u'Source/WebCore/ChangeLog', u'Source/WebCore/WebCore.xcodeproj/project.pbxproj', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp', u'Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h', u'Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp', '--commit-queue']" exit_code: 1
ERROR: Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:131:  Declaration has space between type name and * in *didRemoveLastElementInList  [whitespace/declaration] [3]
Total errors found: 1 in 10 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 57 Geoffrey Garen 2013-12-19 19:25:19 PST
Comment on attachment 219712 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219712&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:67
> +    RetainPtr<CFDictionaryRef> dict = adoptCF(CFDictionaryCreate(0, keys, values, 6, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));

kNumCreationParameters

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:68
> +    for (unsigned i = 0; i < 6; i++)

kNumCreationParameters

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:86
> +ImageBufferBackingStoreCache::IOSurfaceInfoWithCreationParams::IOSurfaceInfoWithCreationParams(IOSurfaceInfo&& info, CGColorSpaceModel colorSpace)
> +    : m_prev(nullptr)
> +    , m_next(nullptr)
> +    , m_info(std::forward<IOSurfaceInfo>(info))
> +    , m_colorSpace(colorSpace)
> +{
> +}

This doesn't look like the right way to do the C++ move idiom.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:112
> +    auto* toAdd = new IOSurfaceInfoWithCreationParams(info);

Should be "auto".

It's not good to take a const& and pass it to a constructor intended to do a move operation. "const&" means "don't modify my data" and "move" means "take all my data away".

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:133
> +    if (didRemoveLastElementInList)
> +        *didRemoveLastElementInList = iter->value.isEmpty();
> +    else
> +        m_cachedSurfaces.remove(iter);

This out parameter is pretty awkward. Can you arrange for the delete function to remove the empty list? That's part of the job of having a helper function -- we want a single place to manage the memory.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:137
> +bool ImageBufferBackingStoreCache::findAcceptableCachedSurface(const IntSize& size, CGColorSpaceModel colorSpace, bool needExactSize, IOSurfaceInfoWithCreationParams& outInfo)

I still think this should be called "take", since it removes an item from the cache.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:145
> +            outInfo = deleteFromCache(i, info, nullptr);

I would call this "take". A C++ programmer should instinctively fear and loathe any line of code that says "x = delete y".

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:200
> +    // Evict

This code right below this comment doesn't do what this comment says.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:224
> +    Vector<CachedSurfaceKey> bucketsToRemove;
> +    bucket = m_cachedSurfaces.begin();
> +    while (m_pixelsCached + surfaceArea > kMaxPixelsCached) {
> +        bool shouldRemoveEmptyEntry;
> +        deleteFromCache(bucket, bucket->value.head(), &shouldRemoveEmptyEntry);
> +        if (shouldRemoveEmptyEntry)
> +            bucketsToRemove.append(bucket->key);
> +        ++bucket;
> +        if (bucket == m_cachedSurfaces.end()) {
> +            clearEmptyBuckets(bucketsToRemove);
> +            bucket = m_cachedSurfaces.begin();
> +        }
> +    }
> +    clearEmptyBuckets(bucketsToRemove);

This is too much code and CPU time for a not-very-good eviction algorithm. Let's at least get the benefits of a not-very-good eviction algorithm, and keep things simple.

Let's go with removing begin().head() repeatedly.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:62
> +    IOSurfaceInfo getIOSurface(const IntSize&, RetainPtr<CGColorSpaceRef>, bool needExactSize);

I'd call this "getOrAllocate".

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:63
> +    void releaseIOSurface(RetainPtr<IOSurfaceRef>);

I would call this "deallocate". No need to mention IOSurface in the name thrice -- it's already in the argument signature part of the name, and in the class name. "deallocate" helps indicate that things not deallocated will cause memory leaks in the cache. It's important to call that out because most caches don't work that way.
Comment 58 Simon Fraser (smfr) 2013-12-19 19:50:39 PST
Comment on attachment 219712 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219712&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:47
> +    struct IOSurfaceInfo {

"info" is a weird name for something that owns the actual data. It sounds more like a metadata container.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:52
> +        IOSurfaceInfo(RetainPtr<IOSurfaceRef> surface, RetainPtr<CGContextRef> context)

Odd to pass RetainPtrs here.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:91
> +        CGColorSpaceModel m_colorSpace;

You need to hold onto a CGColorSpaceRef, not just the model. But why do you need to retain this and the CGContextRef?

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:94
> +    typedef std::pair<int, int> CachedSurfaceKey;

This could be an IntSize.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:101
> +    CachedSurfaceKey convertSizeToKey(const IntSize& size)
> +    {
> +        return std::make_pair(WTF::roundUpToMultipleOf(8, size.width()), WTF::roundUpToMultipleOf(8, size.height()));
> +    }

static?

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:115
> +    bool findAcceptableCachedSurface(const IntSize&, CGColorSpaceModel, bool needExactSize, IOSurfaceInfoWithCreationParams& outInfo);
> +    bool isAcceptableSurface(const IOSurfaceInfoWithCreationParams&, const IntSize&, CGColorSpaceModel, bool needExactSize);

const
Comment 59 Myles C. Maxfield 2013-12-19 22:30:47 PST
Comment on attachment 219712 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219712&action=review

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:67
>> +    RetainPtr<CFDictionaryRef> dict = adoptCF(CFDictionaryCreate(0, keys, values, 6, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
> 
> kNumCreationParameters

Oops. Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:68
>> +    for (unsigned i = 0; i < 6; i++)
> 
> kNumCreationParameters

Oops. Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:86
>> +}
> 
> This doesn't look like the right way to do the C++ move idiom.

It isn't intended to be a move constructor. I've removed the && to make this more straightforward.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:112
>> +    auto* toAdd = new IOSurfaceInfoWithCreationParams(info);
> 
> Should be "auto".
> 
> It's not good to take a const& and pass it to a constructor intended to do a move operation. "const&" means "don't modify my data" and "move" means "take all my data away".

My original intention was to copy the object, but moving the object would be better here.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:133
>> +        m_cachedSurfaces.remove(iter);
> 
> This out parameter is pretty awkward. Can you arrange for the delete function to remove the empty list? That's part of the job of having a helper function -- we want a single place to manage the memory.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:137
>> +bool ImageBufferBackingStoreCache::findAcceptableCachedSurface(const IntSize& size, CGColorSpaceModel colorSpace, bool needExactSize, IOSurfaceInfoWithCreationParams& outInfo)
> 
> I still think this should be called "take", since it removes an item from the cache.

Done

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:145
>> +            outInfo = deleteFromCache(i, info, nullptr);
> 
> I would call this "take". A C++ programmer should instinctively fear and loathe any line of code that says "x = delete y".

After inspection, there is no reason why deleteFromCache has to return a value; the caller already has a pointer to the object being deleted. I'll make it a void function instead, and keep its name.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:200
>> +    // Evict
> 
> This code right below this comment doesn't do what this comment says.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:224
>> +    clearEmptyBuckets(bucketsToRemove);
> 
> This is too much code and CPU time for a not-very-good eviction algorithm. Let's at least get the benefits of a not-very-good eviction algorithm, and keep things simple.
> 
> Let's go with removing begin().head() repeatedly.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:47
>> +    struct IOSurfaceInfo {
> 
> "info" is a weird name for something that owns the actual data. It sounds more like a metadata container.

I've renamed this to IOSurfaceAndContext, and I've renamed IOSurfaceInfoWithCreationParams accordingly.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:52
>> +        IOSurfaceInfo(RetainPtr<IOSurfaceRef> surface, RetainPtr<CGContextRef> context)
> 
> Odd to pass RetainPtrs here.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:62
>> +    IOSurfaceInfo getIOSurface(const IntSize&, RetainPtr<CGColorSpaceRef>, bool needExactSize);
> 
> I'd call this "getOrAllocate".

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:63
>> +    void releaseIOSurface(RetainPtr<IOSurfaceRef>);
> 
> I would call this "deallocate". No need to mention IOSurface in the name thrice -- it's already in the argument signature part of the name, and in the class name. "deallocate" helps indicate that things not deallocated will cause memory leaks in the cache. It's important to call that out because most caches don't work that way.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:91
>> +        CGColorSpaceModel m_colorSpace;
> 
> You need to hold onto a CGColorSpaceRef, not just the model. But why do you need to retain this and the CGContextRef?

Done. I hold on to it so I can see if an item in the cache matches the creation parameters that the client asks for.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:94
>> +    typedef std::pair<int, int> CachedSurfaceKey;
> 
> This could be an IntSize.

the hash function isn't declared for IntSizes

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:101
>> +    }
> 
> static?

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:115
>> +    bool isAcceptableSurface(const IOSurfaceInfoWithCreationParams&, const IntSize&, CGColorSpaceModel, bool needExactSize);
> 
> const

Done.
Comment 60 Myles C. Maxfield 2013-12-19 22:40:23 PST
Created attachment 219732 [details]
Patch
Comment 61 Geoffrey Garen 2013-12-20 13:18:09 PST
Comment on attachment 219732 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219732&action=review

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:78
> +bool ImageBufferBackingStoreCache::isAcceptableSurface(IOSurfaceAndContextWithCreationParams& info, IntSize& requestedSize, CGColorSpaceRef colorSpace, bool needExactSize)

These arguments should be const&.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:126
> +            outInfo = std::move(*info);
> +            deleteFromCache(i, info);

This is basically use after free, since deletedFromCache will use info after it has been moved.
Comment 62 Myles C. Maxfield 2013-12-20 13:32:12 PST
Comment on attachment 219732 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219732&action=review

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:78
>> +bool ImageBufferBackingStoreCache::isAcceptableSurface(IOSurfaceAndContextWithCreationParams& info, IntSize& requestedSize, CGColorSpaceRef colorSpace, bool needExactSize)
> 
> These arguments should be const&.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:126
>> +            deleteFromCache(i, info);
> 
> This is basically use after free, since deletedFromCache will use info after it has been moved.

Done.
Comment 63 Myles C. Maxfield 2013-12-20 14:09:03 PST
Created attachment 219792 [details]
Patch
Comment 64 Geoffrey Garen 2013-12-20 14:27:35 PST
Comment on attachment 219792 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219792&action=review

r=me

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:116
> +    return result;

You gotta move result, too, or no optimization is guaranteed.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:171
> +    IntSize surfaceSize = IntSize(IOSurfaceGetWidth(ioSurface), IOSurfaceGetHeight(ioSurface));

"= IntSize"

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:192
> +    // Clear opportunistically so CG has more time to carry it out

Let's put a period at the end of this, to make it a sentence.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:101
> +    // If we find an acceptable surface, this function removes it from the cache as
> +    // well as placing it in the out parameter

Period at end of sentence, please.

> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:102
> +    bool tryTakeAcceptableCachedSurface(const IntSize&, CGColorSpaceRef, bool needExactSize, IOSurfaceAndContextWithCreationParams& outInfo);

Let's call this tryTakeFromCache, since it's a wrapper around takeFromCache.

> PerformanceTests/Canvas/reuse.html:7
> +var numCreated = 10000;

The period of this benchmark seems so big that no reasonably-sized cache will ever get a hit. So, this benchmark is artificially biased toward giant caches, and it doesn't test much in the way of eviction algorithm.

Maybe just change it to fewer canvases.
Comment 65 Myles C. Maxfield 2013-12-20 14:35:47 PST
Comment on attachment 219792 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=219792&action=review

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:116
>> +    return result;
> 
> You gotta move result, too, or no optimization is guaranteed.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:171
>> +    IntSize surfaceSize = IntSize(IOSurfaceGetWidth(ioSurface), IOSurfaceGetHeight(ioSurface));
> 
> "= IntSize"

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.cpp:192
>> +    // Clear opportunistically so CG has more time to carry it out
> 
> Let's put a period at the end of this, to make it a sentence.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:101
>> +    // well as placing it in the out parameter
> 
> Period at end of sentence, please.

Done.

>> Source/WebCore/platform/graphics/cg/ImageBufferBackingStoreCache.h:102
>> +    bool tryTakeAcceptableCachedSurface(const IntSize&, CGColorSpaceRef, bool needExactSize, IOSurfaceAndContextWithCreationParams& outInfo);
> 
> Let's call this tryTakeFromCache, since it's a wrapper around takeFromCache.

Done.

>> PerformanceTests/Canvas/reuse.html:7
>> +var numCreated = 10000;
> 
> The period of this benchmark seems so big that no reasonably-sized cache will ever get a hit. So, this benchmark is artificially biased toward giant caches, and it doesn't test much in the way of eviction algorithm.
> 
> Maybe just change it to fewer canvases.

Done.
Comment 66 WebKit Commit Bot 2013-12-23 10:19:50 PST
Re-opened since this is blocked by bug 126164
Comment 67 Alexey Proskuryakov 2013-12-23 10:25:50 PST
Rolled out in <https://trac.webkit.org/r161001>. This seems to have made multiple canvas tests flaky:

fast/canvas/canvas-to-canvas.html
fast/canvas/canvas-style-intact-after-text.html
fast/canvas/canvas-strokeText-invalid-maxWidth.html
...and more

I couldn't reproduce the flakiness locally. Will roll back in if this doesn't help tests.
Comment 68 Alexey Proskuryakov 2013-12-23 13:35:27 PST
Comment on attachment 219792 [details]
Patch

The rollout did fix the tests, so removing r+ flag from the latest patch.
Comment 69 Tim Horton 2013-12-28 07:44:49 PST
(In reply to comment #67)
> Rolled out in <https://trac.webkit.org/r161001>. This seems to have made multiple canvas tests flaky:
> 
> fast/canvas/canvas-to-canvas.html
> fast/canvas/canvas-style-intact-after-text.html
> fast/canvas/canvas-strokeText-invalid-maxWidth.html
> ...and more
> 
> I couldn't reproduce the flakiness locally. Will roll back in if this doesn't help tests.

On both Mavericks and Mountain Lion, and both WebKit1 and WebKit2, it looks like?

I can't reproduce either :(
Comment 70 Myles C. Maxfield 2014-01-06 14:16:58 PST
I have tried running tests again on the same hardware as the bots, but cannot reproduce there either
Comment 71 Jon Lee 2014-01-07 00:46:18 PST
(In reply to comment #70)
> I have tried running tests again on the same hardware as the bots, but cannot reproduce there either

Is it possible because the bots are not attached to screens?
Comment 72 Myles C. Maxfield 2014-01-07 13:33:49 PST
The hardware I tested on was not attached to a screen.
Comment 73 Ryosuke Niwa 2014-01-07 13:42:53 PST
You need to boot the machine in the state where display cable is not connected.  Disconnecting a display after the fact has no effect.
Comment 74 Ryosuke Niwa 2014-01-07 13:43:55 PST
Also... you can't have VNC, etc... connected to the machine.  The machine needs to be in a state where there has been no visual output since it had booted.
Comment 75 Myles C. Maxfield 2014-01-07 14:49:44 PST
rniwa: It was in that state. lforschler had an idea to test if the machine not having a monitor had anything to do with it, so we devised a test :)
Comment 76 Myles C. Maxfield 2015-08-26 23:51:01 PDT
Tim has taken this over.