Home | History | Annotate | Download | only in resources
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/time/time.h"
      6 #include "cc/debug/lap_timer.h"
      7 #include "cc/resources/raster_buffer.h"
      8 #include "cc/resources/tile.h"
      9 #include "cc/resources/tile_priority.h"
     10 #include "cc/test/begin_frame_args_test.h"
     11 #include "cc/test/fake_impl_proxy.h"
     12 #include "cc/test/fake_layer_tree_host_impl.h"
     13 #include "cc/test/fake_output_surface.h"
     14 #include "cc/test/fake_output_surface_client.h"
     15 #include "cc/test/fake_picture_layer_impl.h"
     16 #include "cc/test/fake_picture_pile_impl.h"
     17 #include "cc/test/fake_tile_manager.h"
     18 #include "cc/test/fake_tile_manager_client.h"
     19 #include "cc/test/impl_side_painting_settings.h"
     20 #include "cc/test/test_shared_bitmap_manager.h"
     21 #include "cc/test/test_tile_priorities.h"
     22 #include "cc/trees/layer_tree_impl.h"
     23 
     24 #include "testing/gtest/include/gtest/gtest.h"
     25 #include "testing/perf/perf_test.h"
     26 
     27 #include "ui/gfx/frame_time.h"
     28 
     29 namespace cc {
     30 
     31 namespace {
     32 
     33 static const int kTimeLimitMillis = 2000;
     34 static const int kWarmupRuns = 5;
     35 static const int kTimeCheckInterval = 10;
     36 
     37 class FakeRasterizerImpl : public Rasterizer, public RasterizerTaskClient {
     38  public:
     39   // Overridden from Rasterizer:
     40   virtual void SetClient(RasterizerClient* client) OVERRIDE {}
     41   virtual void Shutdown() OVERRIDE {}
     42   virtual void ScheduleTasks(RasterTaskQueue* queue) OVERRIDE {
     43     for (RasterTaskQueue::Item::Vector::const_iterator it =
     44              queue->items.begin();
     45          it != queue->items.end();
     46          ++it) {
     47       RasterTask* task = it->task;
     48 
     49       task->WillSchedule();
     50       task->ScheduleOnOriginThread(this);
     51       task->DidSchedule();
     52 
     53       completed_tasks_.push_back(task);
     54     }
     55   }
     56   virtual void CheckForCompletedTasks() OVERRIDE {
     57     for (RasterTask::Vector::iterator it = completed_tasks_.begin();
     58          it != completed_tasks_.end();
     59          ++it) {
     60       RasterTask* task = it->get();
     61 
     62       task->WillComplete();
     63       task->CompleteOnOriginThread(this);
     64       task->DidComplete();
     65 
     66       task->RunReplyOnOriginThread();
     67     }
     68     completed_tasks_.clear();
     69   }
     70 
     71   // Overridden from RasterizerTaskClient:
     72   virtual scoped_ptr<RasterBuffer> AcquireBufferForRaster(
     73       const Resource* resource) OVERRIDE {
     74     return scoped_ptr<RasterBuffer>();
     75   }
     76   virtual void ReleaseBufferForRaster(
     77       scoped_ptr<RasterBuffer> buffer) OVERRIDE {}
     78 
     79  private:
     80   RasterTask::Vector completed_tasks_;
     81 };
     82 base::LazyInstance<FakeRasterizerImpl> g_fake_rasterizer =
     83     LAZY_INSTANCE_INITIALIZER;
     84 
     85 class TileManagerPerfTest : public testing::Test {
     86  public:
     87   TileManagerPerfTest()
     88       : memory_limit_policy_(ALLOW_ANYTHING),
     89         max_tiles_(10000),
     90         id_(7),
     91         proxy_(base::MessageLoopProxy::current()),
     92         host_impl_(ImplSidePaintingSettings(10000),
     93                    &proxy_,
     94                    &shared_bitmap_manager_),
     95         timer_(kWarmupRuns,
     96                base::TimeDelta::FromMilliseconds(kTimeLimitMillis),
     97                kTimeCheckInterval) {}
     98 
     99   void SetTreePriority(TreePriority tree_priority) {
    100     GlobalStateThatImpactsTilePriority state;
    101     gfx::Size tile_size(256, 256);
    102 
    103     state.soft_memory_limit_in_bytes = 100 * 1000 * 1000;
    104     state.num_resources_limit = max_tiles_;
    105     state.hard_memory_limit_in_bytes = state.soft_memory_limit_in_bytes * 2;
    106     state.memory_limit_policy = memory_limit_policy_;
    107     state.tree_priority = tree_priority;
    108 
    109     global_state_ = state;
    110     host_impl_.resource_pool()->SetResourceUsageLimits(
    111         state.soft_memory_limit_in_bytes, 0, state.num_resources_limit);
    112     host_impl_.tile_manager()->SetGlobalStateForTesting(state);
    113   }
    114 
    115   virtual void SetUp() OVERRIDE {
    116     picture_pile_ = FakePicturePileImpl::CreateInfiniteFilledPile();
    117     InitializeRenderer();
    118     SetTreePriority(SAME_PRIORITY_FOR_BOTH_TREES);
    119   }
    120 
    121   virtual void InitializeRenderer() {
    122     host_impl_.InitializeRenderer(
    123         FakeOutputSurface::Create3d().PassAs<OutputSurface>());
    124     tile_manager()->SetRasterizerForTesting(g_fake_rasterizer.Pointer());
    125   }
    126 
    127   void SetupDefaultTrees(const gfx::Size& layer_bounds) {
    128     gfx::Size tile_size(100, 100);
    129 
    130     scoped_refptr<FakePicturePileImpl> pending_pile =
    131         FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
    132     scoped_refptr<FakePicturePileImpl> active_pile =
    133         FakePicturePileImpl::CreateFilledPile(tile_size, layer_bounds);
    134 
    135     SetupTrees(pending_pile, active_pile);
    136   }
    137 
    138   void ActivateTree() {
    139     host_impl_.ActivateSyncTree();
    140     CHECK(!host_impl_.pending_tree());
    141     pending_root_layer_ = NULL;
    142     active_root_layer_ = static_cast<FakePictureLayerImpl*>(
    143         host_impl_.active_tree()->LayerById(id_));
    144   }
    145 
    146   void SetupDefaultTreesWithFixedTileSize(const gfx::Size& layer_bounds,
    147                                           const gfx::Size& tile_size) {
    148     SetupDefaultTrees(layer_bounds);
    149     pending_root_layer_->set_fixed_tile_size(tile_size);
    150     active_root_layer_->set_fixed_tile_size(tile_size);
    151   }
    152 
    153   void SetupTrees(scoped_refptr<PicturePileImpl> pending_pile,
    154                   scoped_refptr<PicturePileImpl> active_pile) {
    155     SetupPendingTree(active_pile);
    156     ActivateTree();
    157     SetupPendingTree(pending_pile);
    158   }
    159 
    160   void SetupPendingTree(scoped_refptr<PicturePileImpl> pile) {
    161     host_impl_.CreatePendingTree();
    162     LayerTreeImpl* pending_tree = host_impl_.pending_tree();
    163     // Clear recycled tree.
    164     pending_tree->DetachLayerTree();
    165 
    166     scoped_ptr<FakePictureLayerImpl> pending_layer =
    167         FakePictureLayerImpl::CreateWithPile(pending_tree, id_, pile);
    168     pending_layer->SetDrawsContent(true);
    169     pending_tree->SetRootLayer(pending_layer.PassAs<LayerImpl>());
    170 
    171     pending_root_layer_ = static_cast<FakePictureLayerImpl*>(
    172         host_impl_.pending_tree()->LayerById(id_));
    173     pending_root_layer_->DoPostCommitInitializationIfNeeded();
    174   }
    175 
    176   void CreateHighLowResAndSetAllTilesVisible() {
    177     // Active layer must get updated first so pending layer can share from it.
    178     active_root_layer_->CreateDefaultTilingsAndTiles();
    179     active_root_layer_->SetAllTilesVisible();
    180     pending_root_layer_->CreateDefaultTilingsAndTiles();
    181     pending_root_layer_->SetAllTilesVisible();
    182   }
    183 
    184   void RunRasterQueueConstructTest(const std::string& test_name,
    185                                    int layer_count) {
    186     TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
    187                                  SMOOTHNESS_TAKES_PRIORITY,
    188                                  NEW_CONTENT_TAKES_PRIORITY};
    189     int priority_count = 0;
    190 
    191     std::vector<LayerImpl*> layers = CreateLayers(layer_count, 10);
    192     bool resourceless_software_draw = false;
    193     for (unsigned i = 0; i < layers.size(); ++i) {
    194       layers[i]->UpdateTiles(Occlusion(), resourceless_software_draw);
    195     }
    196 
    197     timer_.Reset();
    198     do {
    199       RasterTilePriorityQueue queue;
    200       host_impl_.BuildRasterQueue(&queue, priorities[priority_count]);
    201       priority_count = (priority_count + 1) % arraysize(priorities);
    202       timer_.NextLap();
    203     } while (!timer_.HasTimeLimitExpired());
    204 
    205     perf_test::PrintResult("tile_manager_raster_tile_queue_construct",
    206                            "",
    207                            test_name,
    208                            timer_.LapsPerSecond(),
    209                            "runs/s",
    210                            true);
    211   }
    212 
    213   void RunRasterQueueConstructAndIterateTest(const std::string& test_name,
    214                                              int layer_count,
    215                                              unsigned tile_count) {
    216     TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
    217                                  SMOOTHNESS_TAKES_PRIORITY,
    218                                  NEW_CONTENT_TAKES_PRIORITY};
    219 
    220     std::vector<LayerImpl*> layers = CreateLayers(layer_count, 100);
    221     bool resourceless_software_draw = false;
    222     for (unsigned i = 0; i < layers.size(); ++i) {
    223       layers[i]->UpdateTiles(Occlusion(), resourceless_software_draw);
    224     }
    225 
    226     int priority_count = 0;
    227     timer_.Reset();
    228     do {
    229       int count = tile_count;
    230       RasterTilePriorityQueue queue;
    231       host_impl_.BuildRasterQueue(&queue, priorities[priority_count]);
    232       while (count--) {
    233         ASSERT_FALSE(queue.IsEmpty());
    234         ASSERT_TRUE(queue.Top() != NULL);
    235         queue.Pop();
    236       }
    237       priority_count = (priority_count + 1) % arraysize(priorities);
    238       timer_.NextLap();
    239     } while (!timer_.HasTimeLimitExpired());
    240 
    241     perf_test::PrintResult(
    242         "tile_manager_raster_tile_queue_construct_and_iterate",
    243         "",
    244         test_name,
    245         timer_.LapsPerSecond(),
    246         "runs/s",
    247         true);
    248   }
    249 
    250   void RunEvictionQueueConstructTest(const std::string& test_name,
    251                                      int layer_count) {
    252     TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
    253                                  SMOOTHNESS_TAKES_PRIORITY,
    254                                  NEW_CONTENT_TAKES_PRIORITY};
    255     int priority_count = 0;
    256 
    257     std::vector<LayerImpl*> layers = CreateLayers(layer_count, 10);
    258     bool resourceless_software_draw = false;
    259     for (unsigned i = 0; i < layers.size(); ++i) {
    260       FakePictureLayerImpl* layer =
    261           static_cast<FakePictureLayerImpl*>(layers[i]);
    262       layer->UpdateTiles(Occlusion(), resourceless_software_draw);
    263       for (size_t j = 0; j < layer->GetTilings()->num_tilings(); ++j) {
    264         tile_manager()->InitializeTilesWithResourcesForTesting(
    265             layer->GetTilings()->tiling_at(j)->AllTilesForTesting());
    266       }
    267     }
    268 
    269     timer_.Reset();
    270     do {
    271       EvictionTilePriorityQueue queue;
    272       host_impl_.BuildEvictionQueue(&queue, priorities[priority_count]);
    273       priority_count = (priority_count + 1) % arraysize(priorities);
    274       timer_.NextLap();
    275     } while (!timer_.HasTimeLimitExpired());
    276 
    277     perf_test::PrintResult("tile_manager_eviction_tile_queue_construct",
    278                            "",
    279                            test_name,
    280                            timer_.LapsPerSecond(),
    281                            "runs/s",
    282                            true);
    283   }
    284 
    285   void RunEvictionQueueConstructAndIterateTest(const std::string& test_name,
    286                                                int layer_count,
    287                                                unsigned tile_count) {
    288     TreePriority priorities[] = {SAME_PRIORITY_FOR_BOTH_TREES,
    289                                  SMOOTHNESS_TAKES_PRIORITY,
    290                                  NEW_CONTENT_TAKES_PRIORITY};
    291     int priority_count = 0;
    292 
    293     std::vector<LayerImpl*> layers = CreateLayers(layer_count, tile_count);
    294     bool resourceless_software_draw = false;
    295     for (unsigned i = 0; i < layers.size(); ++i) {
    296       FakePictureLayerImpl* layer =
    297           static_cast<FakePictureLayerImpl*>(layers[i]);
    298       layer->UpdateTiles(Occlusion(), resourceless_software_draw);
    299       for (size_t j = 0; j < layer->GetTilings()->num_tilings(); ++j) {
    300         tile_manager()->InitializeTilesWithResourcesForTesting(
    301             layer->GetTilings()->tiling_at(j)->AllTilesForTesting());
    302       }
    303     }
    304 
    305     timer_.Reset();
    306     do {
    307       int count = tile_count;
    308       EvictionTilePriorityQueue queue;
    309       host_impl_.BuildEvictionQueue(&queue, priorities[priority_count]);
    310       while (count--) {
    311         ASSERT_FALSE(queue.IsEmpty());
    312         ASSERT_TRUE(queue.Top() != NULL);
    313         queue.Pop();
    314       }
    315       priority_count = (priority_count + 1) % arraysize(priorities);
    316       timer_.NextLap();
    317     } while (!timer_.HasTimeLimitExpired());
    318 
    319     perf_test::PrintResult(
    320         "tile_manager_eviction_tile_queue_construct_and_iterate",
    321         "",
    322         test_name,
    323         timer_.LapsPerSecond(),
    324         "runs/s",
    325         true);
    326   }
    327 
    328   std::vector<LayerImpl*> CreateLayers(int layer_count,
    329                                        int tiles_per_layer_count) {
    330     // Compute the width/height required for high res to get
    331     // tiles_per_layer_count tiles.
    332     float width = std::sqrt(static_cast<float>(tiles_per_layer_count));
    333     float height = tiles_per_layer_count / width;
    334 
    335     // Adjust the width and height to account for the fact that tiles
    336     // are bigger than 1x1. Also, account for the fact that that we
    337     // will be creating one high res and one low res tiling. That is,
    338     // width and height should be smaller by sqrt(1 + low_res_scale).
    339     // This gives us _approximately_ correct counts.
    340     width *= settings_.default_tile_size.width() /
    341              std::sqrt(1 + settings_.low_res_contents_scale_factor);
    342     height *= settings_.default_tile_size.height() /
    343               std::sqrt(1 + settings_.low_res_contents_scale_factor);
    344 
    345     // Ensure that we start with blank trees and no tiles.
    346     host_impl_.ResetTreesForTesting();
    347     tile_manager()->FreeResourcesAndCleanUpReleasedTilesForTesting();
    348 
    349     gfx::Size layer_bounds(width, height);
    350     gfx::Size viewport(width / 5, height / 5);
    351     host_impl_.SetViewportSize(viewport);
    352     SetupDefaultTreesWithFixedTileSize(layer_bounds,
    353                                        settings_.default_tile_size);
    354 
    355     active_root_layer_->CreateDefaultTilingsAndTiles();
    356     pending_root_layer_->CreateDefaultTilingsAndTiles();
    357 
    358     std::vector<LayerImpl*> layers;
    359 
    360     // Pending layer counts as one layer.
    361     layers.push_back(pending_root_layer_);
    362     int next_id = id_ + 1;
    363 
    364     // Create the rest of the layers as children of the root layer.
    365     while (static_cast<int>(layers.size()) < layer_count) {
    366       scoped_ptr<FakePictureLayerImpl> layer =
    367           FakePictureLayerImpl::CreateWithPile(
    368               host_impl_.pending_tree(), next_id, picture_pile_);
    369       layer->SetBounds(layer_bounds);
    370       layers.push_back(layer.get());
    371       pending_root_layer_->AddChild(layer.PassAs<LayerImpl>());
    372 
    373       FakePictureLayerImpl* fake_layer =
    374           static_cast<FakePictureLayerImpl*>(layers.back());
    375 
    376       fake_layer->SetDrawsContent(true);
    377       fake_layer->DoPostCommitInitializationIfNeeded();
    378       fake_layer->CreateDefaultTilingsAndTiles();
    379       ++next_id;
    380     }
    381 
    382     return layers;
    383   }
    384 
    385   GlobalStateThatImpactsTilePriority GlobalStateForTest() {
    386     GlobalStateThatImpactsTilePriority state;
    387     gfx::Size tile_size = settings_.default_tile_size;
    388     state.soft_memory_limit_in_bytes =
    389         10000u * 4u *
    390         static_cast<size_t>(tile_size.width() * tile_size.height());
    391     state.hard_memory_limit_in_bytes = state.soft_memory_limit_in_bytes;
    392     state.num_resources_limit = 10000;
    393     state.memory_limit_policy = ALLOW_ANYTHING;
    394     state.tree_priority = SMOOTHNESS_TAKES_PRIORITY;
    395     return state;
    396   }
    397 
    398   void RunManageTilesTest(const std::string& test_name,
    399                           int layer_count,
    400                           int approximate_tile_count_per_layer) {
    401     std::vector<LayerImpl*> layers =
    402         CreateLayers(layer_count, approximate_tile_count_per_layer);
    403     timer_.Reset();
    404     bool resourceless_software_draw = false;
    405     do {
    406       BeginFrameArgs args = CreateBeginFrameArgsForTesting();
    407       host_impl_.UpdateCurrentBeginFrameArgs(args);
    408       for (unsigned i = 0; i < layers.size(); ++i) {
    409         layers[i]->UpdateTiles(Occlusion(), resourceless_software_draw);
    410       }
    411 
    412       GlobalStateThatImpactsTilePriority global_state(GlobalStateForTest());
    413       tile_manager()->ManageTiles(global_state);
    414       tile_manager()->UpdateVisibleTiles();
    415       timer_.NextLap();
    416       host_impl_.ResetCurrentBeginFrameArgsForNextFrame();
    417     } while (!timer_.HasTimeLimitExpired());
    418 
    419     perf_test::PrintResult(
    420         "manage_tiles", "", test_name, timer_.LapsPerSecond(), "runs/s", true);
    421   }
    422 
    423   TileManager* tile_manager() { return host_impl_.tile_manager(); }
    424 
    425  protected:
    426   GlobalStateThatImpactsTilePriority global_state_;
    427 
    428   TestSharedBitmapManager shared_bitmap_manager_;
    429   TileMemoryLimitPolicy memory_limit_policy_;
    430   int max_tiles_;
    431   int id_;
    432   FakeImplProxy proxy_;
    433   FakeLayerTreeHostImpl host_impl_;
    434   FakePictureLayerImpl* pending_root_layer_;
    435   FakePictureLayerImpl* active_root_layer_;
    436   LapTimer timer_;
    437   scoped_refptr<FakePicturePileImpl> picture_pile_;
    438   LayerTreeSettings settings_;
    439 };
    440 
    441 TEST_F(TileManagerPerfTest, ManageTiles) {
    442   RunManageTilesTest("2_100", 2, 100);
    443   RunManageTilesTest("2_500", 2, 500);
    444   RunManageTilesTest("2_1000", 2, 1000);
    445   RunManageTilesTest("10_100", 10, 100);
    446   RunManageTilesTest("10_500", 10, 500);
    447   RunManageTilesTest("10_1000", 10, 1000);
    448   RunManageTilesTest("50_100", 100, 100);
    449   RunManageTilesTest("50_500", 100, 500);
    450   RunManageTilesTest("50_1000", 100, 1000);
    451 }
    452 
    453 TEST_F(TileManagerPerfTest, RasterTileQueueConstruct) {
    454   RunRasterQueueConstructTest("2", 2);
    455   RunRasterQueueConstructTest("10", 10);
    456   RunRasterQueueConstructTest("50", 50);
    457 }
    458 
    459 TEST_F(TileManagerPerfTest, RasterTileQueueConstructAndIterate) {
    460   RunRasterQueueConstructAndIterateTest("2_16", 2, 16);
    461   RunRasterQueueConstructAndIterateTest("2_32", 2, 32);
    462   RunRasterQueueConstructAndIterateTest("2_64", 2, 64);
    463   RunRasterQueueConstructAndIterateTest("2_128", 2, 128);
    464   RunRasterQueueConstructAndIterateTest("10_16", 10, 16);
    465   RunRasterQueueConstructAndIterateTest("10_32", 10, 32);
    466   RunRasterQueueConstructAndIterateTest("10_64", 10, 64);
    467   RunRasterQueueConstructAndIterateTest("10_128", 10, 128);
    468   RunRasterQueueConstructAndIterateTest("50_16", 50, 16);
    469   RunRasterQueueConstructAndIterateTest("50_32", 50, 32);
    470   RunRasterQueueConstructAndIterateTest("50_64", 50, 64);
    471   RunRasterQueueConstructAndIterateTest("50_128", 50, 128);
    472 }
    473 
    474 TEST_F(TileManagerPerfTest, EvictionTileQueueConstruct) {
    475   RunEvictionQueueConstructTest("2", 2);
    476   RunEvictionQueueConstructTest("10", 10);
    477   RunEvictionQueueConstructTest("50", 50);
    478 }
    479 
    480 TEST_F(TileManagerPerfTest, EvictionTileQueueConstructAndIterate) {
    481   RunEvictionQueueConstructAndIterateTest("2_16", 2, 16);
    482   RunEvictionQueueConstructAndIterateTest("2_32", 2, 32);
    483   RunEvictionQueueConstructAndIterateTest("2_64", 2, 64);
    484   RunEvictionQueueConstructAndIterateTest("2_128", 2, 128);
    485   RunEvictionQueueConstructAndIterateTest("10_16", 10, 16);
    486   RunEvictionQueueConstructAndIterateTest("10_32", 10, 32);
    487   RunEvictionQueueConstructAndIterateTest("10_64", 10, 64);
    488   RunEvictionQueueConstructAndIterateTest("10_128", 10, 128);
    489   RunEvictionQueueConstructAndIterateTest("50_16", 50, 16);
    490   RunEvictionQueueConstructAndIterateTest("50_32", 50, 32);
    491   RunEvictionQueueConstructAndIterateTest("50_64", 50, 64);
    492   RunEvictionQueueConstructAndIterateTest("50_128", 50, 128);
    493 }
    494 
    495 }  // namespace
    496 
    497 }  // namespace cc
    498