10102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang/* 20102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * Copyright (C) 2017 The Android Open Source Project 30102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * 40102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 50102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * you may not use this file except in compliance with the License. 60102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * You may obtain a copy of the License at 70102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * 80102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * http://www.apache.org/licenses/LICENSE-2.0 90102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * 100102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * Unless required by applicable law or agreed to in writing, software 110102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * distributed under the License is distributed on an "AS IS" BASIS, 120102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * See the License for the specific language governing permissions and 140102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang * limitations under the License. 150102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang */ 160102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang#include <android-base/stringprintf.h> 170102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang#include <timestatsproto/TimeStatsHelper.h> 180102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 190102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang#include <array> 200102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 210102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang#define HISTOGRAM_SIZE 85 220102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 230102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhangusing android::base::StringAppendF; 240102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhangusing android::base::StringPrintf; 250102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 260102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhangnamespace android { 270102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhangnamespace surfaceflinger { 280102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 290102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang// Time buckets for histogram, the calculated time deltas will be lower bounded 300102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang// to the buckets in this array. 310102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhangstatic const std::array<int32_t, HISTOGRAM_SIZE> histogramConfig = 320102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 330102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 340102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 34, 36, 38, 40, 42, 44, 46, 48, 50, 54, 58, 62, 66, 70, 74, 78, 82, 350102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 86, 90, 94, 98, 102, 106, 110, 114, 118, 122, 126, 130, 134, 138, 142, 146, 150, 360102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000}; 370102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 380102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhangvoid TimeStatsHelper::Histogram::insert(int32_t delta) { 390102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang if (delta < 0) return; 400102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang // std::lower_bound won't work on out of range values 410102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang if (delta > histogramConfig[HISTOGRAM_SIZE - 1]) { 420102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang hist[histogramConfig[HISTOGRAM_SIZE - 1]]++; 430102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang return; 440102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 450102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang auto iter = std::lower_bound(histogramConfig.begin(), histogramConfig.end(), delta); 460102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang hist[*iter]++; 470102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} 480102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 498a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhangfloat TimeStatsHelper::Histogram::averageTime() const { 500102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang int64_t ret = 0; 510102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang int64_t count = 0; 528a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang for (auto& ele : hist) { 530102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang count += ele.second; 540102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang ret += ele.first * ele.second; 550102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 560102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang return static_cast<float>(ret) / count; 570102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} 580102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 598a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhangstd::string TimeStatsHelper::Histogram::toString() const { 600102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang std::string result; 610102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang for (int32_t i = 0; i < HISTOGRAM_SIZE; ++i) { 620102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang int32_t bucket = histogramConfig[i]; 638a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang int32_t count = (hist.count(bucket) == 0) ? 0 : hist.at(bucket); 640102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "%dms=%d ", bucket, count); 650102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 660102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang result.back() = '\n'; 670102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang return result; 680102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} 690102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 708a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhangstd::string TimeStatsHelper::TimeStatsLayer::toString() const { 710102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang std::string result = ""; 720102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "layerName = %s\n", layerName.c_str()); 730102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "packageName = %s\n", packageName.c_str()); 740102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart)); 750102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd)); 760102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "totalFrames= %d\n", totalFrames); 778a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang auto iter = deltas.find("present2present"); 788a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang if (iter != deltas.end()) { 798a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang StringAppendF(&result, "averageFPS = %.3f\n", 1000.0 / iter->second.averageTime()); 800102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 818a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang for (auto& ele : deltas) { 820102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "%s histogram is as below:\n", ele.first.c_str()); 830102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "%s", ele.second.toString().c_str()); 840102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 850102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 860102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang return result; 870102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} 880102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 898a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhangstd::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional<uint32_t> maxLayers) const { 900102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang std::string result = "SurfaceFlinger TimeStats:\n"; 910102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "statsStart = %lld\n", static_cast<long long int>(statsStart)); 920102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "statsEnd = %lld\n", static_cast<long long int>(statsEnd)); 930102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "totalFrames= %d\n", totalFrames); 940102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "missedFrames= %d\n", missedFrames); 950102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "clientCompositionFrames= %d\n", clientCompositionFrames); 960102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "TimeStats for each layer is as below:\n"); 978a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang const auto dumpStats = generateDumpStats(maxLayers); 988a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang for (auto& ele : dumpStats) { 990102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang StringAppendF(&result, "%s", ele->toString().c_str()); 1000102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 1010102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 1020102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang return result; 1030102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} 1040102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 1058a4015c8d7d0316fa422ed53db7e972310f6758bYiwei ZhangSFTimeStatsLayerProto TimeStatsHelper::TimeStatsLayer::toProto() const { 1060102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang SFTimeStatsLayerProto layerProto; 1070102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang layerProto.set_layer_name(layerName); 1080102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang layerProto.set_package_name(packageName); 1090102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang layerProto.set_stats_start(statsStart); 1100102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang layerProto.set_stats_end(statsEnd); 1110102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang layerProto.set_total_frames(totalFrames); 1128a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang for (auto& ele : deltas) { 1130102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang SFTimeStatsDeltaProto* deltaProto = layerProto.add_deltas(); 1140102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang deltaProto->set_delta_name(ele.first); 1158a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang for (auto& histEle : ele.second.hist) { 1163bef3959e3a8245a04ef43cd1b19dd6d4ea15d37Yiwei Zhang SFTimeStatsHistogramBucketProto* histProto = deltaProto->add_histograms(); 1170102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang histProto->set_render_millis(histEle.first); 1180102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang histProto->set_frame_count(histEle.second); 1190102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 1200102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 1210102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang return layerProto; 1220102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} 1230102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 1248a4015c8d7d0316fa422ed53db7e972310f6758bYiwei ZhangSFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto( 1258a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang std::optional<uint32_t> maxLayers) const { 1260102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang SFTimeStatsGlobalProto globalProto; 1270102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang globalProto.set_stats_start(statsStart); 1280102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang globalProto.set_stats_end(statsEnd); 1290102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang globalProto.set_total_frames(totalFrames); 1300102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang globalProto.set_missed_frames(missedFrames); 1310102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang globalProto.set_client_composition_frames(clientCompositionFrames); 1328a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang const auto dumpStats = generateDumpStats(maxLayers); 1338a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang for (auto& ele : dumpStats) { 1340102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang SFTimeStatsLayerProto* layerProto = globalProto.add_stats(); 1350102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang layerProto->CopyFrom(ele->toProto()); 1360102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang } 1370102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang return globalProto; 1380102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} 1390102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang 1408a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhangstd::vector<TimeStatsHelper::TimeStatsLayer const*> 1418a4015c8d7d0316fa422ed53db7e972310f6758bYiwei ZhangTimeStatsHelper::TimeStatsGlobal::generateDumpStats(std::optional<uint32_t> maxLayers) const { 1428a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang std::vector<TimeStatsLayer const*> dumpStats; 1438a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang for (auto& ele : stats) { 1448a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang dumpStats.push_back(&ele.second); 1458a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang } 1468a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang 1478a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang std::sort(dumpStats.begin(), dumpStats.end(), 1488a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang [](TimeStatsHelper::TimeStatsLayer const* l, 1498a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang TimeStatsHelper::TimeStatsLayer const* r) { 1508a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang return l->totalFrames > r->totalFrames; 1518a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang }); 1528a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang 1538a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang if (maxLayers && (*maxLayers < dumpStats.size())) { 1548a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang dumpStats.resize(*maxLayers); 1558a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang } 1568a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang return dumpStats; 1578a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang} 1588a4015c8d7d0316fa422ed53db7e972310f6758bYiwei Zhang 1590102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} // namespace surfaceflinger 1600102ad2d522de255efabd50adf6c6a27811344f4Yiwei Zhang} // namespace android 161