• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-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 #ifndef PANDA_RUNTIME_PROFILE_SAVER_H_
16 #define PANDA_RUNTIME_PROFILE_SAVER_H_
17 
18 #include <pthread.h>
19 
20 #include <map>
21 #include <set>
22 #include <string>
23 #include <thread>
24 #include <vector>
25 
26 #include "libpandabase/macros.h"
27 #include "libpandabase/os/mutex.h"
28 #include "libpandabase/utils/logger.h"
29 #include "runtime/include/mem/panda_containers.h"
30 #include "runtime/include/mem/panda_string.h"
31 #include "runtime/profilesaver/profile_dump_info.h"
32 
33 namespace ark {
34 
35 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects, readability-identifier-naming)
36 static os::memory::Mutex profile_saver_lock_;
37 
38 /*
39  * NB! we take singleton pattern, multi-threading scenario should be taken more serious considerations.
40  *
41  * e.g. Global Mutex Management or corresponding alternatives should better than
42  * global mutex profile_saver_lock_.
43  *
44  */
45 
46 // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions)
47 class ProfileSaver {
48 public:
49     /*
50      * start the profile saver daemon thread
51      *
52      * output_filename records the profile name, code_paths stores all the locations contain pandafile(aka *.aex)
53      * app_data_dir contains the location of application package file (aka *.hap)
54      */
55     static void Start(const PandaString &outputFilename, const PandaVector<PandaString> &codePaths,
56                       const PandaString &appDataDir);
57 
58     /*
59      * stop the profile saver daemon thread.
60      *
61      * if dump_info == true, dumps the debug information
62      */
63     static void Stop(bool dumpInfo);
64 
65     /*
66      * whether profile saver instance exists.
67      */
68     static bool IsStarted();
69 
70 private:
71     ProfileSaver(const PandaString &outputFilename, const PandaVector<PandaString> &codePaths,
72                  const PandaString &appDir);
73 
74     void AddTrackedLocations(const PandaString &outputFilename, const PandaVector<PandaString> &codePaths,
75                              const PandaString &appDataDir);
76 
77     /*
78      * Callback for pthread_create, we attach/detach this thread to Runtime here
79      */
80     static void *RunProfileSaverThread(void *arg);
81 
82     /*
83      * Run loop for the saver.
84      */
85     void Run();
86 
87     /*
88      * Returns true if the saver is shutting down (ProfileSaver::Stop() has been called, will set this flag).
89      */
90     bool ShuttingDown();
91 
92     /*
93      * Dump functions, we leave it stub and for test until now.
94      */
95     void DumpInfo();
96 
97     /*
98      * Fetches the current resolved classes and methods from the ClassLinker and stores them in the profile_cache_.
99      */
100     void TranverseAndCacheResolvedClassAndMethods();
101 
102     /*
103      * Retrieves the cached ProfileDumpInfo for the given profile filename.
104      * If no entry exists, a new empty one will be created, added to the cache and then returned.
105      */
106     ProfileDumpInfo *GetOrAddCachedProfiledInfo(const PandaString &filename);
107 
108     /*
109      * Processes the existing profiling info from the jit code cache(if exists) and returns
110      * true if it needed to be saved back to disk.
111      */
112     void MergeAndDumpProfileData();
113 
114     static ProfileSaver *instance_;
115 
116     static std::thread profilerSaverDaemonThread_;
117 
118     PandaMap<PandaString, PandaSet<PandaString>> trackedPandafileBaseLocations_;
119 
120     PandaMap<PandaString, ProfileDumpInfo> profileCache_;
121 
122     PandaSet<PandaString> appDataDirs_;
123 
GUARDED_BY(profile_saver_lock_)124     bool shuttingDown_ GUARDED_BY(profile_saver_lock_) {false};
125 
126     struct CntStats {
127     public:
GetMethodCountCntStats128         uint64_t GetMethodCount()
129         {
130             return lastSaveNumberOfMethods_;
131         }
132 
SetMethodCountCntStats133         void SetMethodCount(uint64_t methodcnt)
134         {
135             lastSaveNumberOfMethods_ = methodcnt;
136         }
137 
GetClassCountCntStats138         uint64_t GetClassCount()
139         {
140             return lastSaveNumberOfClasses_;
141         }
142 
SetClassCountCntStats143         void SetClassCount(uint64_t classcnt)
144         {
145             lastSaveNumberOfClasses_ = classcnt;
146         }
147 
148     private:
149         uint64_t lastSaveNumberOfMethods_ {0};
150         uint64_t lastSaveNumberOfClasses_ {0};
151     };
152 
153     PandaMap<PandaString, CntStats> statcache;  // NOLINT(readability-identifier-naming)
154 
155     /*
156      * Retrieves the cached CntStats for the given profile filename.
157      * If no entry exists, a new empty one will be created, added to the cache and then returned.
158      */
159     CntStats *GetOrAddCachedProfiledStatsInfo(const PandaString &filename);
160 
161     NO_COPY_SEMANTIC(ProfileSaver);
162     NO_MOVE_SEMANTIC(ProfileSaver);
163 };
164 
165 }  // namespace ark
166 
167 #endif
168