aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2014-10-09 18:22:41 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-09 18:22:41 -0700
commit092dab98220110e7244ccbbb851efa8ad621ab88 (patch)
tree108d88a67b2a08327444f0573382f7f7ac4ad005 /src
parent232f6b0f90a02bcdac0c5931d5f9cfd08003b10c (diff)
Use BBH reserve hook to preallocate space for tiles.
Before getting too far into changing how SkTileGrid stores its tiles, I figured I'd better see how much I can tweak out the existing format. Cleverly, that way any improvements I make by changing the format will look that much less impressive. This CL looks like it will be a 5-15% win in time spent recording, with no effect on playback. This CL also shrinks the tiles to fit exactly when we're done inserting, using newly added SkTDArray::shrinkToFit(). It's quite cheap to run (maybe taking back 1-2% from those 5-15% wins), and means we'll lug around about 15% fewer bytes in the tile grids. Note though this strategy temporarily uses up to 30% more memory while building the tile grid. For our largest SKPs, that's maybe 75-100K extra. BUG=skia: Committed: https://skia.googlesource.com/skia/+/52455cbc02d7f480d988ae7cdacc11ad69078c2c CQ_EXTRA_TRYBOTS=tryserver.skia:Canary-Chrome-Ubuntu13.10-Ninja-x86_64-ToT-Trybot Review URL: https://codereview.chromium.org/639823005
Diffstat (limited to 'src')
-rw-r--r--src/core/SkTileGrid.cpp27
-rw-r--r--src/core/SkTileGrid.h3
2 files changed, 30 insertions, 0 deletions
diff --git a/src/core/SkTileGrid.cpp b/src/core/SkTileGrid.cpp
index 8b96b73fa1..30ca4b9179 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 {
diff --git a/src/core/SkTileGrid.h b/src/core/SkTileGrid.h
index e8a0d96a65..fd7584fd9c 100644
--- a/src/core/SkTileGrid.h
+++ b/src/core/SkTileGrid.h
@@ -39,6 +39,9 @@ public:
// For testing.
int tileCount(int x, int y) { return fTiles[y * fXTiles + x].count(); }
+ virtual void reserve(unsigned opCount) SK_OVERRIDE;
+ virtual void flushDeferredInserts() SK_OVERRIDE;
+
private:
void commonAdjust(SkRect*) const;
void userToGrid(const SkRect&, SkIRect* grid) const;