1/*
2 * Copyright (c) 2024 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 LIBPANDABASE_UTILS_TIMERS_H
17#define LIBPANDABASE_UTILS_TIMERS_H
18
19#include <chrono>
20#include <mutex>
21#include <string>
22#include <string_view>
23#include <unordered_map>
24#include <vector>
25
26namespace panda {
27// Event list
28constexpr std::string_view EVENT_TOTAL = "Total";
29constexpr std::string_view EVENT_COMPILE = "Compile";
30constexpr std::string_view EVENT_RESOLVE_DEPS = "Resolve file dep relations";
31constexpr std::string_view EVENT_EMIT_ABC = "Emit abc";
32constexpr std::string_view EVENT_READ_INPUT_AND_CACHE = "Read input and cache";
33constexpr std::string_view EVENT_COMPILE_FILE = "Compile file";
34constexpr std::string_view EVENT_COMPILE_ABC_FILE = "Compile abc file";
35constexpr std::string_view EVENT_COMPILE_ABC_FILE_RECORD = "Compile abc file record";
36constexpr std::string_view EVENT_UPDATE_ABC_PKG_VERSION = "Update abc package version";
37constexpr std::string_view EVENT_UPDATE_ABC_PROGRAM_STRING = "Update abc program string";
38constexpr std::string_view EVENT_UPDATE_ABC_PROG_CACHE = "Update abc program cache";
39constexpr std::string_view EVENT_OPTIMIZE_PROGRAM = "Optimize program";
40constexpr std::string_view EVENT_PARSE = "Parse";
41constexpr std::string_view EVENT_COMPILE_TO_PROGRAM = "Compile to program";
42constexpr std::string_view EVENT_EMIT_SINGLE_PROGRAM = "Emit single program";
43constexpr std::string_view EVENT_EMIT_MERGED_PROGRAM = "Emit merged program";
44constexpr std::string_view EVENT_EMIT_CACHE_FILE = "Emit cache file";
45
46// Event level, indicating the level of an event, where each event is a sub-event of the nearest preceding level event.
47// The top-level event's level is 0
48enum EventLevel {
49    ZEROTH = 0,
50    FIRST,
51    SECOND,
52    THIRD,
53    FORTH,
54    FIFTH,
55    SIXTH
56};
57
58// Holds pairs of {event, level} according to the order during compilation process.
59// When adding new events later, please add them in the compilation order for ease of reading and maintenance.
60const std::unordered_map<std::string_view, EventLevel> eventMap = {
61    { EVENT_TOTAL, EventLevel::ZEROTH },
62    { EVENT_COMPILE, EventLevel::FIRST },
63    { EVENT_READ_INPUT_AND_CACHE, EventLevel::SECOND },
64    { EVENT_COMPILE_ABC_FILE, EventLevel::SECOND },
65    { EVENT_COMPILE_ABC_FILE_RECORD, EventLevel::FORTH },
66    { EVENT_UPDATE_ABC_PKG_VERSION, EventLevel::THIRD },
67    { EVENT_UPDATE_ABC_PROGRAM_STRING, EventLevel::THIRD },
68    { EVENT_UPDATE_ABC_PROG_CACHE, EventLevel::THIRD },
69    { EVENT_COMPILE_FILE, EventLevel::SECOND },
70    { EVENT_PARSE, EventLevel::THIRD },
71    { EVENT_COMPILE_TO_PROGRAM, EventLevel::THIRD },
72    { EVENT_OPTIMIZE_PROGRAM, EventLevel::SECOND },
73    { EVENT_RESOLVE_DEPS, EventLevel::FIRST },
74    { EVENT_EMIT_ABC, EventLevel::FIRST },
75    { EVENT_EMIT_SINGLE_PROGRAM, EventLevel::SECOND },
76    { EVENT_EMIT_MERGED_PROGRAM, EventLevel::SECOND },
77    { EVENT_EMIT_CACHE_FILE, EventLevel::SECOND },
78};
79
80typedef void (*TimeStartFunc)(const std::string_view event, std::string fileName);
81typedef void (*TimeEndFunc)(const std::string_view event, std::string fileName);
82typedef std::chrono::time_point<std::chrono::steady_clock> TimePoint;
83
84struct TimePointRecord {
85    TimePoint startTime;
86    TimePoint endTime;
87};
88
89struct TimeRecord {
90    std::unordered_map<std::string, TimePointRecord> timePoints;  // pair of {fileName, TimePointRecord}
91    std::string event;
92    int level;
93};
94
95class Timer {
96public:
97    static void InitializeTimer(std::string &perfFile);
98    static void PrintTimers();
99
100    static TimeStartFunc timerStart;
101    static TimeEndFunc timerEnd;
102
103private:
104    static void TimerStartImpl(const std::string_view event, std::string fileName = "");
105    static void TimerEndImpl(const std::string_view event, std::string fileName = "");
106    static void TimerStartDoNothing(const std::string_view event, std::string fileName = "") {}
107    static void TimerEndDoNothing(const std::string_view event, std::string fileName = "") {}
108
109    static std::unordered_map<std::string_view, TimeRecord> timers_;  // pair of {event, TimeRecord}
110    static std::vector<std::string_view> events_;
111    static std::mutex mutex_;
112    static std::string perfFile_;
113};
114
115}  // namespace panda
116
117#endif  // LIBPANDABASE_UTILS_TIMERS_H
118