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