1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef GRAPHIC_LITE_GRAPHIC_PERFORMANCE_H
17 #define GRAPHIC_LITE_GRAPHIC_PERFORMANCE_H
18 
19 #include "graphic_config.h"
20 #if ENABLE_DEBUG && ENABLE_DEBUG_PERFORMANCE_TRACE
21 #include <limits>
22 #include <map>
23 #include <signal.h>
24 #include <string>
25 #include <stdio.h>
26 #include <sys/time.h>
27 
28 namespace OHOS {
29 static const char* perfTitle[5] = {"name", "times", "minCost", "maxCost", "avgCost"};
30 struct PerformanceItem {
31     int32_t times;
32     int32_t minCost;
33     int32_t maxCost;
34     double avgCost;
35     int32_t warmup;
36 };
37 
38 class Performance {
39 public:
40     static Performance* GetInstance();
41 
SigUsr(int signo)42     static void SigUsr(int signo)
43     {
44         if (signo == SIGUSR1) {
45             Performance::GetInstance()->SetPrintFlag();
46         }
47     }
48 
RegisterSIGUSR1()49     void RegisterSIGUSR1()
50     {
51         if (signal(SIGUSR1, SigUsr) == SIG_ERR) {
52             printf("signal error!\n");
53         }
54     }
55 
UpdateItem(std::string name,int32_t cost,int32_t warmup)56     void UpdateItem(std::string name, int32_t cost, int32_t warmup)
57     {
58         if (mapPerfItem.find(name) == mapPerfItem.end()) {
59             PerformanceItem item = { 0 };
60             item.times = 1;
61             item.minCost = INT32_MAX;
62             item.warmup = warmup;
63             mapPerfItem[name] = item;
64         } else {
65             PerformanceItem& item = mapPerfItem[name];
66             item.times++;
67         }
68         PerformanceItem& item = mapPerfItem[name];
69         if (item.times > warmup) {
70             item.minCost = (item.minCost > cost) ? cost : item.minCost;
71             item.maxCost = (item.maxCost < cost) ? cost : item.maxCost;
72             item.avgCost = item.avgCost + 1.0 * (cost - item.avgCost) / (item.times - warmup);
73         }
74     }
75 
SetPrintFlag()76     void SetPrintFlag()
77     {
78         needPrint = true;
79     }
80 
PrintResult()81     void PrintResult()
82     {
83         if (!needPrint) {
84             return;
85         }
86         needPrint = false;
87         /*
88          * perfTitle[0]: "name"
89          * perfTitle[1]: "times"
90          * perfTitle[2]: "minCost"
91          * perfTitle[3]: "maxCost"
92          * perfTitle[4]: "avgCost"
93          */
94         printf("\n%-40s%-20s%-20s%-20s%-20s\n", perfTitle[0], perfTitle[1], perfTitle[2], perfTitle[3], perfTitle[4]);
95         for (auto iter = mapPerfItem.begin(); iter != mapPerfItem.end(); iter++) {
96             if (iter->second.times - iter->second.warmup > 0) {
97                 printf("%-40s%-20d%-20d%-20d%-20.2lf\n",
98                        iter->first.c_str(),
99                        iter->second.times - iter->second.warmup,
100                        iter->second.minCost,
101                        iter->second.maxCost,
102                        iter->second.avgCost);
103             }
104         }
105     }
106 
107 private:
Performance()108     Performance() {}
~Performance()109     ~Performance() {}
110 
111     std::map<std::string, PerformanceItem> mapPerfItem;
112     bool needPrint = false;
113 };
114 
115 class PerformanceTool {
116 public:
PerformanceTool(const char * name)117     explicit PerformanceTool(const char* name) : name_(name)
118     {
119         gettimeofday(&tm_, NULL);
120     }
121 
PerformanceTool(const char * name,int32_t warmup)122     PerformanceTool(const char* name, int32_t warmup) : name_(name), warmUp_(warmup)
123     {
124         gettimeofday(&tm_, NULL);
125     }
126 
~PerformanceTool()127     ~PerformanceTool()
128     {
129         struct timeval now;
130         gettimeofday(&now, NULL);
131         // 1000000: 1,000,000 microseconds per second
132         int32_t cost = (now.tv_sec - tm_.tv_sec) * 1000000 + (now.tv_usec - tm_.tv_usec);
133         Performance::GetInstance()->UpdateItem(name_, cost, warmUp_);
134     }
135 private:
136     std::string name_;
137     int32_t warmUp_ = 0;
138     struct timeval tm_;
139 };
140 } // namespace OHOS
141 #define DEBUG_PERFORMANCE_TRACE_AUTO()             OHOS::PerformanceTool __tmp__(__FUNCTION__)
142 #define DEBUG_PERFORMANCE_TRACE_WARMUP(x, warmup)  OHOS::PerformanceTool __tmp__(x, warmup)
143 #define DEBUG_PERFORMANCE_TRACE(x)                 OHOS::PerformanceTool __tmp__(x)
144 #define DEBUG_PERFORMANCE_REGISTER_SIG()           OHOS::Performance::GetInstance()->RegisterSIGUSR1()
145 #define DEBUG_PERFORMANCE_PRINT_RESULT()           OHOS::Performance::GetInstance()->PrintResult()
146 #else
147 #define DEBUG_PERFORMANCE_TRACE_AUTO()
148 #define DEBUG_PERFORMANCE_TRACE_WARMUP(x, warmup)
149 #define DEBUG_PERFORMANCE_TRACE(x)
150 #define DEBUG_PERFORMANCE_REGISTER_SIG()
151 #define DEBUG_PERFORMANCE_PRINT_RESULT()
152 #endif
153 #endif
154