OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include <ctype.h> | 8 #include <ctype.h> |
9 | 9 |
10 #include "nanobench.h" | 10 #include "nanobench.h" |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
481 break; | 481 break; |
482 } | 482 } |
483 | 483 |
484 if (!target->init(info, bench)) { | 484 if (!target->init(info, bench)) { |
485 delete target; | 485 delete target; |
486 return NULL; | 486 return NULL; |
487 } | 487 } |
488 return target; | 488 return target; |
489 } | 489 } |
490 | 490 |
491 // Creates targets for a benchmark and a set of configs. | |
492 static void create_targets(SkTDArray<Target*>* targets, Benchmark* b, | |
493 const SkTDArray<Config>& configs) { | |
494 for (int i = 0; i < configs.count(); ++i) { | |
495 if (Target* t = is_enabled(b, configs[i])) { | |
496 targets->push(t); | |
497 } | |
498 | |
499 } | |
500 } | |
501 | |
502 /* | 491 /* |
503 * Returns true if set up for a subset decode succeeds, false otherwise | 492 * Returns true if set up for a subset decode succeeds, false otherwise |
504 * If the set-up succeeds, the width and height parameters will be set | 493 * If the set-up succeeds, the width and height parameters will be set |
505 */ | 494 */ |
506 static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool
useCodec, | 495 static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool
useCodec, |
507 int* width, int* height) { | 496 int* width, int* height) { |
508 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); | 497 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); |
509 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded)); | 498 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded)); |
510 | 499 |
511 // Check that we can create a codec or image decoder. | 500 // Check that we can create a codec or image decoder. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 | 540 |
552 // Check if the image is large enough for a meaningful subset benchmark. | 541 // Check if the image is large enough for a meaningful subset benchmark. |
553 if (*width <= 512 && *height <= 512) { | 542 if (*width <= 512 && *height <= 512) { |
554 // This should not print a message since it is not an error. | 543 // This should not print a message since it is not an error. |
555 return false; | 544 return false; |
556 } | 545 } |
557 | 546 |
558 return true; | 547 return true; |
559 } | 548 } |
560 | 549 |
| 550 static void cleanup_run(Target* target) { |
| 551 SkDELETE(target); |
| 552 #if SK_SUPPORT_GPU |
| 553 if (FLAGS_abandonGpuContext) { |
| 554 gGrFactory->abandonContexts(); |
| 555 } |
| 556 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) { |
| 557 gGrFactory->destroyContexts(); |
| 558 } |
| 559 #endif |
| 560 } |
| 561 |
561 class BenchmarkStream { | 562 class BenchmarkStream { |
562 public: | 563 public: |
563 BenchmarkStream() : fBenches(BenchRegistry::Head()) | 564 BenchmarkStream() : fBenches(BenchRegistry::Head()) |
564 , fGMs(skiagm::GMRegistry::Head()) | 565 , fGMs(skiagm::GMRegistry::Head()) |
565 , fCurrentRecording(0) | 566 , fCurrentRecording(0) |
566 , fCurrentScale(0) | 567 , fCurrentScale(0) |
567 , fCurrentSKP(0) | 568 , fCurrentSKP(0) |
568 , fCurrentUseMPD(0) | 569 , fCurrentUseMPD(0) |
569 , fCurrentCodec(0) | 570 , fCurrentCodec(0) |
570 , fCurrentImage(0) | 571 , fCurrentImage(0) |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 create_configs(&configs); | 1020 create_configs(&configs); |
1020 | 1021 |
1021 int runs = 0; | 1022 int runs = 0; |
1022 BenchmarkStream benchStream; | 1023 BenchmarkStream benchStream; |
1023 while (Benchmark* b = benchStream.next()) { | 1024 while (Benchmark* b = benchStream.next()) { |
1024 SkAutoTDelete<Benchmark> bench(b); | 1025 SkAutoTDelete<Benchmark> bench(b); |
1025 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName()))
{ | 1026 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, bench->getUniqueName()))
{ |
1026 continue; | 1027 continue; |
1027 } | 1028 } |
1028 | 1029 |
1029 SkTDArray<Target*> targets; | 1030 if (!configs.isEmpty()) { |
1030 create_targets(&targets, bench.get(), configs); | |
1031 | |
1032 if (!targets.isEmpty()) { | |
1033 log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSi
ze().fY); | 1031 log->bench(bench->getUniqueName(), bench->getSize().fX, bench->getSi
ze().fY); |
1034 bench->preDraw(); | 1032 bench->preDraw(); |
1035 } | 1033 } |
1036 for (int j = 0; j < targets.count(); j++) { | 1034 for (int i = 0; i < configs.count(); ++i) { |
| 1035 Target* target = is_enabled(b, configs[i]); |
| 1036 if (!target) { |
| 1037 continue; |
| 1038 } |
| 1039 |
1037 // During HWUI output this canvas may be NULL. | 1040 // During HWUI output this canvas may be NULL. |
1038 SkCanvas* canvas = targets[j]->getCanvas(); | 1041 SkCanvas* canvas = target->getCanvas(); |
1039 const char* config = targets[j]->config.name; | 1042 const char* config = target->config.name; |
1040 | 1043 |
1041 targets[j]->setup(); | 1044 target->setup(); |
1042 bench->perCanvasPreDraw(canvas); | 1045 bench->perCanvasPreDraw(canvas); |
1043 | 1046 |
1044 int maxFrameLag; | 1047 int maxFrameLag; |
1045 const int loops = targets[j]->needsFrameTiming(&maxFrameLag) | 1048 const int loops = target->needsFrameTiming(&maxFrameLag) |
1046 ? setup_gpu_bench(targets[j], bench.get(), maxFrameLag) | 1049 ? setup_gpu_bench(target, bench.get(), maxFrameLag) |
1047 : setup_cpu_bench(overhead, targets[j], bench.get()); | 1050 : setup_cpu_bench(overhead, target, bench.get()); |
1048 | 1051 |
1049 if (kTimedSampling != FLAGS_samples) { | 1052 if (kTimedSampling != FLAGS_samples) { |
1050 samples.reset(FLAGS_samples); | 1053 samples.reset(FLAGS_samples); |
1051 for (int s = 0; s < FLAGS_samples; s++) { | 1054 for (int s = 0; s < FLAGS_samples; s++) { |
1052 samples[s] = time(loops, bench, targets[j]) / loops; | 1055 samples[s] = time(loops, bench, target) / loops; |
1053 } | 1056 } |
1054 } else if (samplingTimeMs) { | 1057 } else if (samplingTimeMs) { |
1055 samples.reset(); | 1058 samples.reset(); |
1056 if (FLAGS_verbose) { | 1059 if (FLAGS_verbose) { |
1057 SkDebugf("Begin sampling %s for %ims\n", | 1060 SkDebugf("Begin sampling %s for %ims\n", |
1058 bench->getUniqueName(), static_cast<int>(samplingTi
meMs)); | 1061 bench->getUniqueName(), static_cast<int>(samplingTi
meMs)); |
1059 } | 1062 } |
1060 WallTimer timer; | 1063 WallTimer timer; |
1061 timer.start(); | 1064 timer.start(); |
1062 do { | 1065 do { |
1063 samples.push_back(time(loops, bench, targets[j]) / loops); | 1066 samples.push_back(time(loops, bench, target) / loops); |
1064 timer.end(); | 1067 timer.end(); |
1065 } while (timer.fWall < samplingTimeMs); | 1068 } while (timer.fWall < samplingTimeMs); |
1066 } | 1069 } |
1067 | 1070 |
1068 bench->perCanvasPostDraw(canvas); | 1071 bench->perCanvasPostDraw(canvas); |
1069 | 1072 |
1070 if (Benchmark::kNonRendering_Backend != targets[j]->config.backend &
& | 1073 if (Benchmark::kNonRendering_Backend != target->config.backend && |
1071 !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { | 1074 !FLAGS_writePath.isEmpty() && FLAGS_writePath[0]) { |
1072 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); | 1075 SkString pngFilename = SkOSPath::Join(FLAGS_writePath[0], config
); |
1073 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); | 1076 pngFilename = SkOSPath::Join(pngFilename.c_str(), bench->getUniq
ueName()); |
1074 pngFilename.append(".png"); | 1077 pngFilename.append(".png"); |
1075 write_canvas_png(targets[j], pngFilename); | 1078 write_canvas_png(target, pngFilename); |
1076 } | 1079 } |
1077 | 1080 |
1078 if (kFailedLoops == loops) { | 1081 if (kFailedLoops == loops) { |
1079 // Can't be timed. A warning note has already been printed. | 1082 // Can't be timed. A warning note has already been printed. |
| 1083 cleanup_run(target); |
1080 continue; | 1084 continue; |
1081 } | 1085 } |
1082 | 1086 |
1083 Stats stats(samples); | 1087 Stats stats(samples); |
1084 log->config(config); | 1088 log->config(config); |
1085 log->configOption("name", bench->getName()); | 1089 log->configOption("name", bench->getName()); |
1086 benchStream.fillCurrentOptions(log.get()); | 1090 benchStream.fillCurrentOptions(log.get()); |
1087 targets[j]->fillOptions(log.get()); | 1091 target->fillOptions(log.get()); |
1088 log->metric("min_ms", stats.min); | 1092 log->metric("min_ms", stats.min); |
1089 if (runs++ % FLAGS_flushEvery == 0) { | 1093 if (runs++ % FLAGS_flushEvery == 0) { |
1090 log->flush(); | 1094 log->flush(); |
1091 } | 1095 } |
1092 | 1096 |
1093 if (kAutoTuneLoops != FLAGS_loops) { | 1097 if (kAutoTuneLoops != FLAGS_loops) { |
1094 if (targets.count() == 1) { | 1098 if (configs.count() == 1) { |
1095 config = ""; // Only print the config if we run the same ben
ch on more than one. | 1099 config = ""; // Only print the config if we run the same ben
ch on more than one. |
1096 } | 1100 } |
1097 SkDebugf("%4d/%-4dMB\t%s\t%s\n" | 1101 SkDebugf("%4d/%-4dMB\t%s\t%s\n" |
1098 , sk_tools::getCurrResidentSetSizeMB() | 1102 , sk_tools::getCurrResidentSetSizeMB() |
1099 , sk_tools::getMaxResidentSetSizeMB() | 1103 , sk_tools::getMaxResidentSetSizeMB() |
1100 , bench->getUniqueName() | 1104 , bench->getUniqueName() |
1101 , config); | 1105 , config); |
1102 } else if (FLAGS_verbose) { | 1106 } else if (FLAGS_verbose) { |
1103 for (int i = 0; i < samples.count(); i++) { | 1107 for (int i = 0; i < samples.count(); i++) { |
1104 SkDebugf("%s ", HUMANIZE(samples[i])); | 1108 SkDebugf("%s ", HUMANIZE(samples[i])); |
1105 } | 1109 } |
1106 SkDebugf("%s\n", bench->getUniqueName()); | 1110 SkDebugf("%s\n", bench->getUniqueName()); |
1107 } else if (FLAGS_quiet) { | 1111 } else if (FLAGS_quiet) { |
1108 if (targets.count() == 1) { | 1112 if (configs.count() == 1) { |
1109 config = ""; // Only print the config if we run the same ben
ch on more than one. | 1113 config = ""; // Only print the config if we run the same ben
ch on more than one. |
1110 } | 1114 } |
1111 SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getUniqu
eName(), config); | 1115 SkDebugf("%s\t%s\t%s\n", HUMANIZE(stats.median), bench->getUniqu
eName(), config); |
1112 } else { | 1116 } else { |
1113 const double stddev_percent = 100 * sqrt(stats.var) / stats.mean
; | 1117 const double stddev_percent = 100 * sqrt(stats.var) / stats.mean
; |
1114 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n" | 1118 SkDebugf("%4d/%-4dMB\t%d\t%s\t%s\t%s\t%s\t%.0f%%\t%s\t%s\t%s\n" |
1115 , sk_tools::getCurrResidentSetSizeMB() | 1119 , sk_tools::getCurrResidentSetSizeMB() |
1116 , sk_tools::getMaxResidentSetSizeMB() | 1120 , sk_tools::getMaxResidentSetSizeMB() |
1117 , loops | 1121 , loops |
1118 , HUMANIZE(stats.min) | 1122 , HUMANIZE(stats.min) |
1119 , HUMANIZE(stats.median) | 1123 , HUMANIZE(stats.median) |
1120 , HUMANIZE(stats.mean) | 1124 , HUMANIZE(stats.mean) |
1121 , HUMANIZE(stats.max) | 1125 , HUMANIZE(stats.max) |
1122 , stddev_percent | 1126 , stddev_percent |
1123 , kTimedSampling != FLAGS_samples ? stats.plot.c_str() | 1127 , kTimedSampling != FLAGS_samples ? stats.plot.c_str() |
1124 : to_string(samples.co
unt()).c_str() | 1128 : to_string(samples.co
unt()).c_str() |
1125 , config | 1129 , config |
1126 , bench->getUniqueName() | 1130 , bench->getUniqueName() |
1127 ); | 1131 ); |
1128 } | 1132 } |
1129 #if SK_SUPPORT_GPU | 1133 #if SK_SUPPORT_GPU |
1130 if (FLAGS_gpuStats && | 1134 if (FLAGS_gpuStats && |
1131 Benchmark::kGPU_Backend == targets[j]->config.backend) { | 1135 Benchmark::kGPU_Backend == configs[i].backend) { |
1132 gGrFactory->get(targets[j]->config.ctxType)->printCacheStats(); | 1136 gGrFactory->get(configs[i].ctxType)->printCacheStats(); |
1133 gGrFactory->get(targets[j]->config.ctxType)->printGpuStats(); | 1137 gGrFactory->get(configs[i].ctxType)->printGpuStats(); |
1134 } | 1138 } |
1135 #endif | 1139 #endif |
| 1140 cleanup_run(target); |
1136 } | 1141 } |
1137 targets.deleteAll(); | |
1138 | |
1139 #if SK_SUPPORT_GPU | |
1140 if (FLAGS_abandonGpuContext) { | |
1141 gGrFactory->abandonContexts(); | |
1142 } | |
1143 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) { | |
1144 gGrFactory->destroyContexts(); | |
1145 } | |
1146 #endif | |
1147 } | 1142 } |
1148 | 1143 |
1149 log->bench("memory_usage", 0,0); | 1144 log->bench("memory_usage", 0,0); |
1150 log->config("meta"); | 1145 log->config("meta"); |
1151 log->metric("max_rss_mb", sk_tools::getMaxResidentSetSizeMB()); | 1146 log->metric("max_rss_mb", sk_tools::getMaxResidentSetSizeMB()); |
1152 | 1147 |
1153 #if SK_SUPPORT_GPU | 1148 #if SK_SUPPORT_GPU |
1154 // Make sure we clean up the global GrContextFactory here, otherwise we migh
t race with the | 1149 // Make sure we clean up the global GrContextFactory here, otherwise we migh
t race with the |
1155 // SkEventTracer destructor | 1150 // SkEventTracer destructor |
1156 gGrFactory.reset(NULL); | 1151 gGrFactory.reset(NULL); |
1157 #endif | 1152 #endif |
1158 | 1153 |
1159 return 0; | 1154 return 0; |
1160 } | 1155 } |
1161 | 1156 |
1162 #if !defined SK_BUILD_FOR_IOS | 1157 #if !defined SK_BUILD_FOR_IOS |
1163 int main(int argc, char** argv) { | 1158 int main(int argc, char** argv) { |
1164 SkCommandLineFlags::Parse(argc, argv); | 1159 SkCommandLineFlags::Parse(argc, argv); |
1165 return nanobench_main(); | 1160 return nanobench_main(); |
1166 } | 1161 } |
1167 #endif | 1162 #endif |
OLD | NEW |