/** * Takes argc,argv along with one of the benchmark functions defined above. * Will loop along all skp files and perform measurments. * * Returns a SkScalar representing CPU time taken during benchmark. * As a side effect, it spits the timer result to stdout. * Will return -1.0 on error. */ static bool benchmark_loop( int argc, char **argv, const BenchmarkControl& benchControl, SkTArray<Histogram>& histogram) { static const SkString timeFormat("%f"); TimerData timerData(argc - 1); for (int index = 1; index < argc; ++index) { BenchTimer timer; SkString path(argv[index]); SkAutoTUnref<SkPicture> pic(pic_from_path(path.c_str())); if (NULL == pic) { SkDebugf("Couldn't create picture. Ignoring path: %s\n", path.c_str()); continue; } benchControl.fFunction(benchControl.fType, benchControl.fTileSize, path, pic, &timer); SkAssertResult(timerData.appendTimes(&timer)); histogram[index - 1].fPath = path; histogram[index - 1].fCpuTime = SkDoubleToScalar(timer.fCpu); } const SkString timerResult = timerData.getResult( /*doubleFormat = */ timeFormat.c_str(), /*result = */ TimerData::kAvg_Result, /*configName = */ benchControl.fName.c_str(), /*timerFlags = */ TimerData::kCpu_Flag); const char findStr[] = "= "; int pos = timerResult.find(findStr); if (-1 == pos) { SkDebugf("Unexpected output from TimerData::getResult(...). Unable to parse."); return false; } SkScalar cpuTime = SkDoubleToScalar(atof(timerResult.c_str() + pos + sizeof(findStr) - 1)); if (cpuTime == 0) { // atof returns 0.0 on error. SkDebugf("Unable to read value from timer result.\n"); return false; } return true; }
int tool_main(int argc, char** argv) { SkCommandLineFlags::Parse(argc, argv); SkAutoGraphics ag; bool includeBBoxType[kBBoxTypeCount]; for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { includeBBoxType[bBoxType] = (FLAGS_bb_types.count() == 0) || FLAGS_bb_types.contains(kBBoxHierarchyTypeNames[bBoxType]); } // go through all the pictures SkTArray<Measurement> measurements; for (int index = 0; index < FLAGS_skps.count(); ++index) { const char* path = FLAGS_skps[index]; SkPicture* picture = pic_from_path(path); if (NULL == picture) { SkDebugf("Couldn't create picture. Ignoring path: %s\n", path); continue; } SkDebugf("Benchmarking path: %s\n", path); Measurement& measurement = measurements.push_back(); measurement.fName = path; for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { if (!includeBBoxType[bBoxType]) { continue; } if (FLAGS_playback > 0) { sk_tools::TiledPictureRenderer playbackRenderer; BenchTimer playbackTimer; do_benchmark_work(&playbackRenderer, (BBoxType)bBoxType, picture, FLAGS_playback, &playbackTimer); measurement.fPlaybackAverage[bBoxType] = playbackTimer.fCpu; } if (FLAGS_record > 0) { sk_tools::RecordPictureRenderer recordRenderer; BenchTimer recordTimer; do_benchmark_work(&recordRenderer, (BBoxType)bBoxType, picture, FLAGS_record, &recordTimer); measurement.fRecordAverage[bBoxType] = recordTimer.fCpu; } } } Measurement globalMeasurement; for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { if (!includeBBoxType[bBoxType]) { continue; } globalMeasurement.fPlaybackAverage[bBoxType] = 0; globalMeasurement.fRecordAverage[bBoxType] = 0; for (int index = 0; index < measurements.count(); ++index) { const Measurement& measurement = measurements[index]; globalMeasurement.fPlaybackAverage[bBoxType] += measurement.fPlaybackAverage[bBoxType]; globalMeasurement.fRecordAverage[bBoxType] += measurement.fRecordAverage[bBoxType]; } globalMeasurement.fPlaybackAverage[bBoxType] /= measurements.count(); globalMeasurement.fRecordAverage[bBoxType] /= measurements.count(); } // Output gnuplot readable histogram data.. const char* pbTitle = "bbh_shootout_playback.dat"; const char* recTitle = "bbh_shootout_record.dat"; SkFILEWStream playbackOut(pbTitle); SkFILEWStream recordOut(recTitle); recordOut.writeText("# "); playbackOut.writeText("# "); SkDebugf("---\n"); for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { if (!includeBBoxType[bBoxType]) { continue; } SkString out; out.printf("%s ", kBBoxHierarchyTypeNames[bBoxType]); recordOut.writeText(out.c_str()); playbackOut.writeText(out.c_str()); if (FLAGS_record > 0) { SkDebugf("Average %s recording time: %.3fms\n", kBBoxHierarchyTypeNames[bBoxType], globalMeasurement.fRecordAverage[bBoxType]); } if (FLAGS_playback > 0) { SkDebugf("Average %s playback time: %.3fms\n", kBBoxHierarchyTypeNames[bBoxType], globalMeasurement.fPlaybackAverage[bBoxType]); } } recordOut.writeText("\n"); playbackOut.writeText("\n"); // Write to file, and save recording averages. for (int index = 0; index < measurements.count(); ++index) { const Measurement& measurement = measurements[index]; SkString pbLine; SkString recLine; pbLine.printf("%d", index); recLine.printf("%d", index); for (int bBoxType = 0; bBoxType < kBBoxTypeCount; ++bBoxType) { if (!includeBBoxType[bBoxType]) { continue; } pbLine.appendf(" %f", measurement.fPlaybackAverage[bBoxType]); recLine.appendf(" %f", measurement.fRecordAverage[bBoxType]); } pbLine.appendf("\n"); recLine.appendf("\n"); playbackOut.writeText(pbLine.c_str()); recordOut.writeText(recLine.c_str()); } SkDebugf("\nWrote data to gnuplot-readable files: %s %s\n", pbTitle, recTitle); return 0; }