1c216a01c96d83bd9a90e214af64913e93d39aaccRichard Smith/* 259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith * Copyright 2013 Google Inc. 359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith * 459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith * Use of this source code is governed by a BSD-style license that can be 559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith * found in the LICENSE file. 69eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith */ 79eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith 859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith#include "Timer.h" 959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith#include "Benchmark.h" 1059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith#include "LazyDecodeBitmap.h" 111d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "PictureBenchmark.h" 121d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "PictureRenderer.h" 131d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "SkCommandLineFlags.h" 141d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "SkForceLinking.h" 151d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "SkGraphics.h" 161d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "SkStream.h" 171d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "SkString.h" 181d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith#include "SkTArray.h" 191d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith 201d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smithtypedef sk_tools::PictureRenderer::BBoxHierarchyType BBoxType; 211d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smithstatic const int kBBoxTypeCount = sk_tools::PictureRenderer::kLast_BBoxHierarchyType + 1; 2259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 2359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 2459efe266b804330f4c1f3a1b0ff783e67dd90378Richard SmithDEFINE_string2(skps, r, "", "The list of SKPs to benchmark."); 2559efe266b804330f4c1f3a1b0ff783e67dd90378Richard SmithDEFINE_string(bb_types, "", "The set of bbox types to test. If empty, all are tested. " 2659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith "Should be one or more of none, quadtree, rtree, tilegrid."); 2759efe266b804330f4c1f3a1b0ff783e67dd90378Richard SmithDEFINE_int32(record, 100, "Number of times to record each SKP."); 2859efe266b804330f4c1f3a1b0ff783e67dd90378Richard SmithDEFINE_int32(playback, 1, "Number of times to playback each SKP."); 2959efe266b804330f4c1f3a1b0ff783e67dd90378Richard SmithDEFINE_int32(tilesize, 256, "The size of a tile."); 3059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 3159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smithstruct Measurement { 3259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkString fName; 3359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith double fRecordAverage[kBBoxTypeCount]; 3459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith double fPlaybackAverage[kBBoxTypeCount]; 3559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith}; 3659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 3759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smithconst char* kBBoxHierarchyTypeNames[kBBoxTypeCount] = { 3859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith "none", // kNone_BBoxHierarchyType 3959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith "quadtree", // kQuadTree_BBoxHierarchyType 40f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith "rtree", // kRTree_BBoxHierarchyType 419eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith "tilegrid", // kTileGrid_BBoxHierarchyType 429eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith}; 439eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith 4459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smithstatic SkPicture* pic_from_path(const char path[]) { 4559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkFILEStream stream(path); 4659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (!stream.isValid()) { 479eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith SkDebugf("-- Can't open '%s'\n", path); 489eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith return NULL; 499eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith } 5059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith return SkPicture::CreateFromStream(&stream, &sk_tools::LazyDecodeBitmap); 5159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith} 5259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 5359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith/** 549eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith * This function is the sink to which all work ends up going. 559eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith * @param renderer The renderer to use to perform the work. 5659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith * To measure rendering, use a TiledPictureRenderer. 579eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith * To measure recording, use a RecordPictureRenderer. 589eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith * @param bBoxType The bounding box hierarchy type to use. 599eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith * @param pic The picture to draw to the renderer. 609eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith * @param numRepeats The number of times to repeat the draw. 619eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith * @param timer The timer used to benchmark the work. 6259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith */ 6359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smithstatic void do_benchmark_work(sk_tools::PictureRenderer* renderer, 6459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith BBoxType bBoxType, 6559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkPicture* pic, 6659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith const int numRepeats, 6759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith Timer* timer) { 689eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith renderer->setBBoxHierarchyType(bBoxType); 6959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith renderer->setGridSize(FLAGS_tilesize, FLAGS_tilesize); 7059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith renderer->init(pic, NULL, NULL, NULL, false); 71f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith 72f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith SkDebugf("%s %d times...\n", renderer->getConfigName().c_str(), numRepeats); 73f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith for (int i = 0; i < numRepeats; ++i) { 74f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith renderer->setup(); 75f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith // Render once to fill caches 76f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith renderer->render(); 77f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith // Render again to measure 78f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith timer->start(); 79f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith renderer->render(); 80f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith timer->end(); 81f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith } 82f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith} 83f64699e8db3946e21b5f4a0421cbc58a3e439599Richard Smith 8459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smithint tool_main(int argc, char** argv); 8559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smithint tool_main(int argc, char** argv) { 8659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkCommandLineFlags::Parse(argc, argv); 8759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkAutoGraphics ag; 881d238ea926bbdd04356ce475934fcd4cac654c4bRichard Smith bool includeBBoxType[kBBoxTypeCount]; 896180245e9f63d2927b185ec251fb75aba30f1cacRichard Smith for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { 9059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith includeBBoxType[bBoxType] = (FLAGS_bb_types.count() == 0) || 9159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith FLAGS_bb_types.contains(kBBoxHierarchyTypeNames[bBoxType]); 9259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 9359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith // go through all the pictures 9459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkTArray<Measurement> measurements; 958ef7b203332b0c8d65876a1f5e6d1db4e6f40e4bRichard Smith for (int index = 0; index < FLAGS_skps.count(); ++index) { 968ef7b203332b0c8d65876a1f5e6d1db4e6f40e4bRichard Smith const char* path = FLAGS_skps[index]; 9759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkPicture* picture = pic_from_path(path); 9859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (NULL == picture) { 9959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkDebugf("Couldn't create picture. Ignoring path: %s\n", path); 10059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith continue; 10159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 10259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkDebugf("Benchmarking path: %s\n", path); 103099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith Measurement& measurement = measurements.push_back(); 104099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith measurement.fName = path; 105099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { 106099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith if (!includeBBoxType[bBoxType]) { continue; } 107099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith if (FLAGS_playback > 0) { 108099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith sk_tools::TiledPictureRenderer playbackRenderer; 109099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith Timer playbackTimer; 110099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith do_benchmark_work(&playbackRenderer, (BBoxType)bBoxType, 11159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith picture, FLAGS_playback, &playbackTimer); 11259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith measurement.fPlaybackAverage[bBoxType] = playbackTimer.fCpu; 11359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 11459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (FLAGS_record > 0) { 11559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith sk_tools::RecordPictureRenderer recordRenderer; 11659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith Timer recordTimer; 1179eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith do_benchmark_work(&recordRenderer, (BBoxType)bBoxType, 11859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith picture, FLAGS_record, &recordTimer); 11959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith measurement.fRecordAverage[bBoxType] = recordTimer.fCpu; 12059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 12159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 12259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 12359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 12459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith Measurement globalMeasurement; 12559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { 12659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (!includeBBoxType[bBoxType]) { continue; } 12759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith globalMeasurement.fPlaybackAverage[bBoxType] = 0; 12859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith globalMeasurement.fRecordAverage[bBoxType] = 0; 1299eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith for (int index = 0; index < measurements.count(); ++index) { 1309eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith const Measurement& measurement = measurements[index]; 1319eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith globalMeasurement.fPlaybackAverage[bBoxType] += 1329eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith measurement.fPlaybackAverage[bBoxType]; 1339eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith globalMeasurement.fRecordAverage[bBoxType] += 13459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith measurement.fRecordAverage[bBoxType]; 13559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 13659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith globalMeasurement.fPlaybackAverage[bBoxType] /= measurements.count(); 13759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith globalMeasurement.fRecordAverage[bBoxType] /= measurements.count(); 13859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 13959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 14059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith // Output gnuplot readable histogram data.. 1419eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith const char* pbTitle = "bbh_shootout_playback.dat"; 1429eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith const char* recTitle = "bbh_shootout_record.dat"; 1439eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith SkFILEWStream playbackOut(pbTitle); 1449eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith SkFILEWStream recordOut(recTitle); 1457098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith recordOut.writeText("# "); 1467098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith playbackOut.writeText("# "); 14759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkDebugf("---\n"); 14859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { 14959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (!includeBBoxType[bBoxType]) { continue; } 15059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkString out; 15159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith out.printf("%s ", kBBoxHierarchyTypeNames[bBoxType]); 1529eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith recordOut.writeText(out.c_str()); 15359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith playbackOut.writeText(out.c_str()); 15459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 15559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (FLAGS_record > 0) { 15659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkDebugf("Average %s recording time: %.3fms\n", 15759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith kBBoxHierarchyTypeNames[bBoxType], 15859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith globalMeasurement.fRecordAverage[bBoxType]); 15959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 16059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (FLAGS_playback > 0) { 1619eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith SkDebugf("Average %s playback time: %.3fms\n", 16259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith kBBoxHierarchyTypeNames[bBoxType], 16359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith globalMeasurement.fPlaybackAverage[bBoxType]); 16459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 16559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 16659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith recordOut.writeText("\n"); 16759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith playbackOut.writeText("\n"); 16859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith // Write to file, and save recording averages. 16959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith for (int index = 0; index < measurements.count(); ++index) { 170d7c56e1114bfe7d461786903bb720d2c6efc05a1Richard Smith const Measurement& measurement = measurements[index]; 17159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkString pbLine; 17259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith SkString recLine; 17359efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 17459efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith pbLine.printf("%d", index); 17559efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith recLine.printf("%d", index); 17659efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { 17759efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith if (!includeBBoxType[bBoxType]) { continue; } 17859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith pbLine.appendf(" %f", measurement.fPlaybackAverage[bBoxType]); 17959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith recLine.appendf(" %f", measurement.fRecordAverage[bBoxType]); 18059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith } 1819eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith pbLine.appendf("\n"); 1829eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith recLine.appendf("\n"); 1839eed49c2bb0f37bbfefefd0998b6303a686a66c0Richard Smith playbackOut.writeText(pbLine.c_str()); 1841bf9a9e6a5bdc0de7939908855dcddf46b661800Richard Smith recordOut.writeText(recLine.c_str()); 1851bf9a9e6a5bdc0de7939908855dcddf46b661800Richard Smith } 1861bf9a9e6a5bdc0de7939908855dcddf46b661800Richard Smith SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle); 1871bf9a9e6a5bdc0de7939908855dcddf46b661800Richard Smith return 0; 18859efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith} 18959efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith 19059efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 19159efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smithint main(int argc, char** argv) { 19259efe266b804330f4c1f3a1b0ff783e67dd90378Richard Smith return tool_main(argc, argv); 193099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith} 194099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith#endif 195099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith