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