Index: src/core/SkTileGrid.cpp |
diff --git a/src/core/SkTileGrid.cpp b/src/core/SkTileGrid.cpp |
index 8b96b73fa13f895654c53d7834d28451479bd163..30ca4b9179b7e29d71425a65b0ad4d1dfd31fc8b 100644 |
--- a/src/core/SkTileGrid.cpp |
+++ b/src/core/SkTileGrid.cpp |
@@ -23,6 +23,33 @@ SkTileGrid::~SkTileGrid() { |
SkDELETE_ARRAY(fTiles); |
} |
+void SkTileGrid::reserve(unsigned opCount) { |
+ if (fXTiles * fYTiles == 0) { |
+ return; // A tileless tile grid is nonsensical, but happens in at least cc_unittests. |
+ } |
+ |
+ // If we assume every op we're about to try to insert() falls within our grid bounds, |
+ // then every op has to hit at least one tile. In fact, a quick scan over our small |
+ // SKP set shows that in the average SKP, each op hits two 256x256 tiles. |
+ |
+ // If we take those observations and further assume the ops are distributed evenly |
+ // across the picture, we get this guess for number of ops per tile: |
+ const int opsPerTileGuess = (2 * opCount) / (fXTiles * fYTiles); |
+ |
+ for (SkTDArray<unsigned>* tile = fTiles; tile != fTiles + (fXTiles * fYTiles); tile++) { |
+ tile->setReserve(opsPerTileGuess); |
+ } |
+ |
+ // In practice, this heuristic means we'll temporarily allocate about 30% more bytes |
+ // than if we made no setReserve() calls, but time spent in insert() drops by about 50%. |
+} |
+ |
+void SkTileGrid::flushDeferredInserts() { |
+ for (SkTDArray<unsigned>* tile = fTiles; tile != fTiles + (fXTiles * fYTiles); tile++) { |
+ tile->shrinkToFit(); |
+ } |
+} |
+ |
// Adjustments to user-provided bounds common to both insert() and search(). |
// Call this after making insert- or search- specific adjustments. |
void SkTileGrid::commonAdjust(SkRect* rect) const { |