From 0afb81f2713d00c63a7a06cadb639e78a1964130 Mon Sep 17 00:00:00 2001 From: shawn_hu_ls Date: Sat, 12 Mar 2022 16:24:29 +0800 Subject: [PATCH] Temporarily drop profile saver Signed-off-by: shawn_hu_ls --- runtime/BUILD.gn | 2 - runtime/CMakeLists.txt | 2 - runtime/include/runtime_options.h | 2 - runtime/profilesaver/profile_dump_info.cpp | 575 --------------------- runtime/profilesaver/profile_dump_info.h | 289 ----------- runtime/profilesaver/profile_saver.cpp | 333 ------------ runtime/profilesaver/profile_saver.h | 170 ------ runtime/runtime.cpp | 10 - 8 files changed, 1383 deletions(-) delete mode 100644 runtime/profilesaver/profile_dump_info.cpp delete mode 100644 runtime/profilesaver/profile_dump_info.h delete mode 100644 runtime/profilesaver/profile_saver.cpp delete mode 100644 runtime/profilesaver/profile_saver.h diff --git a/runtime/BUILD.gn b/runtime/BUILD.gn index eef4721019..6106d910a4 100644 --- a/runtime/BUILD.gn +++ b/runtime/BUILD.gn @@ -138,8 +138,6 @@ ohos_static_library("libarkruntime_static") { "object_accessor.cpp", "object_header.cpp", "panda_vm.cpp", - "profilesaver/profile_dump_info.cpp", - "profilesaver/profile_saver.cpp", "runtime.cpp", "runtime_helpers.cpp", "signal_handler.cpp", diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index ad8b7a4f09..ae03cce350 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -128,8 +128,6 @@ set(SOURCES object_accessor.cpp arch/asm_support.cpp signal_handler.cpp - profilesaver/profile_saver.cpp - profilesaver/profile_dump_info.cpp runtime_helpers.cpp handle_scope.cpp file_manager.cpp diff --git a/runtime/include/runtime_options.h b/runtime/include/runtime_options.h index 69eb18a83f..b581969845 100644 --- a/runtime/include/runtime_options.h +++ b/runtime/include/runtime_options.h @@ -38,7 +38,6 @@ class CFrameTest; class StackWalkerTest; class PandaRunner; class CompilerQueueTest; -class ProfileSaverTest; class DynObjectsTest; class JSObjectTest; class JSFunctionTest; @@ -312,7 +311,6 @@ private: friend class panda::test::PandaRunner; friend class verifier::test::VerifierTest; friend class panda::Logger; - friend class test::ProfileSaverTest; friend class panda::test::DynObjectsTest; friend class panda::test::JSObjectTest; friend class panda::test::JSFunctionTest; diff --git a/runtime/profilesaver/profile_dump_info.cpp b/runtime/profilesaver/profile_dump_info.cpp deleted file mode 100644 index 9b70c7a644..0000000000 --- a/runtime/profilesaver/profile_dump_info.cpp +++ /dev/null @@ -1,575 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "runtime/profilesaver/profile_dump_info.h" - -#include -#include -#include - -#include -#include -#include - -#include "libpandabase/os/unix/failure_retry.h" -#include "trace/trace.h" - -#ifndef PATH_MAX -#define PATH_MAX 1024 -#endif - -namespace panda { -static constexpr size_t K_BITS_PER_BYTE = 8; - -static constexpr size_t K_LINE_HEADER_SIZE = 3 * sizeof(uint32_t) + sizeof(uint16_t); -static constexpr size_t K_METHOD_BYTES = 4; -static constexpr size_t K_CLASS_BYTES = 4; - -const uint8_t ProfileDumpInfo::kProfileMagic[] = {'p', 'r', 'o', 'f', '\0'}; // NOLINT -const uint8_t ProfileDumpInfo::kProfileVersion[] = {'0', '1', '\0'}; // NOLINT - -static constexpr uint16_t K_MAX_FILE_KEY_LENGTH = PATH_MAX; // NOLINT - -static bool WriteBuffer(int fd, const uint8_t *buffer, size_t byte_count) -{ // NOLINT - while (byte_count > 0) { - int bytes_written = write(fd, buffer, byte_count); // real place to write - if (bytes_written == -1) { - return false; - } - byte_count -= bytes_written; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - buffer += bytes_written; - } - return true; -} - -static void AddStringToBuffer(PandaVector *buffer, const PandaString &value) -{ // NOLINT - buffer->insert(buffer->end(), value.begin(), value.end()); -} - -template -static void AddUintToBuffer(PandaVector *buffer, T value) -{ - for (size_t i = 0; i < sizeof(T); i++) { - buffer->push_back((value >> (i * K_BITS_PER_BYTE)) & 0xff); // NOLINT - } -} - -/* - * Tests for EOF by trying to read 1 byte from the descriptor. - * Returns: - * 0 if the descriptor is at the EOF, - * -1 if there was an IO error - * 1 if the descriptor has more content to read - */ -// NOLINTNEXTLINE(readability-identifier-naming) -static int testEOF(int fd) -{ - // NOLINTNEXTLINE(modernize-avoid-c-arrays) - uint8_t buffer[1]; - return read(fd, buffer, 1); -} - -int64_t GetFileSizeBytes(const PandaString &filename) -{ - struct stat stat_buf { - }; - int rc = stat(filename.c_str(), &stat_buf); - return rc == 0 ? stat_buf.st_size : -1; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::SerializerBuffer::FillFromFd(int fd, const PandaString &source, - PandaString *error) -{ - size_t byte_count = ptr_end_ - ptr_current_; - uint8_t *buffer = ptr_current_; - while (byte_count > 0) { - int bytes_read = read(fd, buffer, byte_count); - if (bytes_read == 0) { // NOLINT - *error += "Profile EOF reached prematurely for " + source; - return PROFILE_LOAD_BAD_DATA; - } else if (bytes_read < 0) { // NOLINT - *error += "Profile IO error for " + source + ConvertToString(os::Error(errno).ToString()); - return PROFILE_LOAD_IO_ERROR; - } - byte_count -= bytes_read; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - buffer += bytes_read; - } - return PROFILE_LOAD_SUCCESS; -} - -template -T ProfileDumpInfo::SerializerBuffer::ReadUintAndAdvance() -{ - static_assert(std::is_unsigned::value, "Type is not unsigned"); - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - ASSERT(ptr_current_ + sizeof(T) <= ptr_end_); - T value = 0; - for (size_t i = 0; i < sizeof(T); i++) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - value += ptr_current_[i] << (i * K_BITS_PER_BYTE); - } - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - ptr_current_ += sizeof(T); - return value; -} - -bool ProfileDumpInfo::SerializerBuffer::CompareAndAdvance(const uint8_t *data, size_t data_size) -{ - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - if (ptr_current_ + data_size > ptr_end_) { - return false; - } - if (memcmp(ptr_current_, data, data_size) == 0) { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - ptr_current_ += data_size; - return true; - } - return false; -} - -bool ProfileDumpInfo::MergeWith(const ProfileDumpInfo &other) -{ - for (const auto &other_it : other.dump_info_) { - auto info_it = dump_info_.find(other_it.first); - if ((info_it != dump_info_.end()) && (info_it->second.checksum != other_it.second.checksum)) { - LOG(INFO, RUNTIME) << "info_it->second.checksum" << info_it->second.checksum; - LOG(INFO, RUNTIME) << "other_it->second.checksum" << other_it.second.checksum; - LOG(INFO, RUNTIME) << "Checksum mismatch" << other_it.first; - return false; - } - } - LOG(INFO, RUNTIME) << "All checksums match"; - - for (const auto &other_it : other.dump_info_) { - const PandaString &other_profile_location = other_it.first; - const ProfileLineData &other_profile_data = other_it.second; - auto info_it = dump_info_.find(other_profile_location); - if (info_it == dump_info_.end()) { - auto ret = - dump_info_.insert(std::make_pair(other_profile_location, ProfileLineData(other_profile_data.checksum))); - ASSERT(ret.second); - info_it = ret.first; - } - info_it->second.method_wrapper_set.insert(other_profile_data.method_wrapper_set.begin(), - other_profile_data.method_wrapper_set.end()); - info_it->second.class_wrapper_set.insert(other_profile_data.class_wrapper_set.begin(), - other_profile_data.class_wrapper_set.end()); - } - return true; -} - -bool ProfileDumpInfo::AddMethodsAndClasses(const PandaVector &methods, - const PandaSet &resolved_classes) -{ - for (const ExtractedMethod &method : methods) { - if (!AddMethodWrapper(ConvertToString(method.panda_file_->GetFilename()), - method.panda_file_->GetHeader()->checksum, MethodWrapper(method.file_id_.GetOffset()))) { - return false; - } - } - - for (const ExtractedResolvedClasses &class_resolved : resolved_classes) { - if (!AddResolvedClasses(class_resolved)) { - return false; - } - } - return true; -} - -uint64_t ProfileDumpInfo::GetNumberOfMethods() const -{ - uint64_t total = 0; - for (const auto &it : dump_info_) { - total += it.second.method_wrapper_set.size(); - } - return total; -} - -uint64_t ProfileDumpInfo::GetNumberOfResolvedClasses() const -{ - uint64_t total = 0; - for (const auto &it : dump_info_) { - total += it.second.class_wrapper_set.size(); - } - return total; -} - -bool ProfileDumpInfo::ContainsMethod(const ExtractedMethod &method_ref) const -{ - auto info_it = dump_info_.find(ConvertToString(method_ref.panda_file_->GetFilename())); - if (info_it != dump_info_.end()) { - if (method_ref.panda_file_->GetHeader()->checksum != info_it->second.checksum) { - return false; - } - const PandaSet &methods = info_it->second.method_wrapper_set; - return methods.find(MethodWrapper(method_ref.file_id_.GetOffset())) != methods.end(); - } - return false; -} - -bool ProfileDumpInfo::ContainsClass(const panda_file::File &pandafile, uint32_t class_def_idx) const -{ - auto info_it = dump_info_.find(ConvertToString(pandafile.GetFilename())); - if (info_it != dump_info_.end()) { - if (pandafile.GetHeader()->checksum != info_it->second.checksum) { - return false; - } - const PandaSet &classes = info_it->second.class_wrapper_set; - return classes.find(ClassWrapper(class_def_idx)) != classes.end(); - } - return false; -} - -bool ProfileDumpInfo::AddMethodWrapper(const PandaString &panda_file_location, uint32_t checksum, - const ProfileDumpInfo::MethodWrapper &method_to_add) -{ - ProfileLineData *const DATA = GetOrAddProfileLineData(panda_file_location, checksum); - if (DATA == nullptr) { - return false; - } - DATA->method_wrapper_set.insert(method_to_add); - return true; -} - -bool ProfileDumpInfo::AddClassWrapper(const PandaString &panda_file_location, uint32_t checksum, - const ProfileDumpInfo::ClassWrapper &class_to_add) -{ - ProfileLineData *const DATA = GetOrAddProfileLineData(panda_file_location, checksum); - if (DATA == nullptr) { - return false; - } - DATA->class_wrapper_set.insert(class_to_add); - return true; -} - -bool ProfileDumpInfo::AddResolvedClasses(const ExtractedResolvedClasses &classes) -{ // NOLINT(readability-identifier-naming) - const PandaString panda_file_location = classes.GetPandaFileLocation(); // NOLINT(readability-identifier-naming) - const uint32_t checksum = classes.GetPandaFileChecksum(); // NOLINT(readability-identifier-naming) - ProfileLineData *const DATA = GetOrAddProfileLineData(panda_file_location, checksum); - if (DATA == nullptr) { - return false; - } - for (auto const &i : classes.GetClasses()) { - DATA->class_wrapper_set.insert(ClassWrapper(i)); - } - return true; -} - -ProfileDumpInfo::ProfileLineData *ProfileDumpInfo::GetOrAddProfileLineData(const PandaString &panda_file_location, - uint32_t checksum) -{ - auto info_it = dump_info_.find(panda_file_location); - if (info_it == dump_info_.end()) { - auto ret = dump_info_.insert(std::make_pair(panda_file_location, ProfileLineData(checksum))); - ASSERT(ret.second); - info_it = ret.first; - } - if (info_it->second.checksum != checksum) { - LOG(INFO, RUNTIME) << "Checksum mismatch" << panda_file_location; - return nullptr; - } - return &(info_it->second); -} - -bool ProfileDumpInfo::Save(int fd) -{ - ASSERT(fd >= 0); - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - - static constexpr size_t K_MAX_BUFFER_SIZE = 8 * 1024; - PandaVector buffer; // each element 1 byte - - WriteBuffer(fd, kProfileMagic, sizeof(kProfileMagic)); - WriteBuffer(fd, kProfileVersion, sizeof(kProfileVersion)); - AddUintToBuffer(&buffer, static_cast(dump_info_.size())); - - for (const auto &it : dump_info_) { - if (buffer.size() > K_MAX_BUFFER_SIZE) { - if (!WriteBuffer(fd, buffer.data(), buffer.size())) { - return false; - } - buffer.clear(); - } - const PandaString &file_location = it.first; - const ProfileLineData &file_data = it.second; - - if (file_location.size() >= K_MAX_FILE_KEY_LENGTH) { - LOG(INFO, RUNTIME) << "PandaFileKey exceeds allocated limit"; - return false; - } - - size_t required_capacity = buffer.size() + K_LINE_HEADER_SIZE + file_location.size() + - K_METHOD_BYTES * file_data.method_wrapper_set.size() + - K_CLASS_BYTES * file_data.class_wrapper_set.size(); - buffer.reserve(required_capacity); - - ASSERT(file_location.size() <= std::numeric_limits::max()); - ASSERT(file_data.method_wrapper_set.size() <= std::numeric_limits::max()); - ASSERT(file_data.class_wrapper_set.size() <= std::numeric_limits::max()); - - AddUintToBuffer(&buffer, static_cast(file_location.size())); - AddUintToBuffer(&buffer, static_cast(file_data.method_wrapper_set.size())); - AddUintToBuffer(&buffer, static_cast(file_data.class_wrapper_set.size())); - AddUintToBuffer(&buffer, file_data.checksum); - AddStringToBuffer(&buffer, file_location); - - if (UNLIKELY(file_data.empty())) { - LOG(INFO, RUNTIME) << "EMPTY FILE DATA, WERIED!"; - } - - for (auto method_it : file_data.method_wrapper_set) { - AddUintToBuffer(&buffer, method_it.method_id_); - } - for (auto class_it : file_data.class_wrapper_set) { - AddUintToBuffer(&buffer, class_it.class_id_); - } - ASSERT(required_capacity == buffer.size()); - } - return WriteBuffer(fd, buffer.data(), buffer.size()); -} - -bool ProfileDumpInfo::Load(int fd) -{ - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - PandaString error; - ProfileLoadSatus status = LoadInternal(fd, &error); - - if (status == PROFILE_LOAD_SUCCESS) { - return true; - } - LOG(INFO, RUNTIME) << "Error when reading profile " << error; - return false; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::LoadInternal(int fd, PandaString *error) -{ - ASSERT(fd >= 0); - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - - struct stat stat_buffer { - }; - if (fstat(fd, &stat_buffer) != 0) { - return PROFILE_LOAD_IO_ERROR; - } - - if (stat_buffer.st_size == 0) { - LOG(INFO, RUNTIME) << "empty file"; - return PROFILE_LOAD_EMPTYFILE; - } - - uint32_t number_of_lines; - ProfileLoadSatus status = ReadProfileHeader(fd, &number_of_lines, error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - LOG(INFO, RUNTIME) << "number of profile items = " << number_of_lines; - - while (number_of_lines > 0) { - ProfileLineHeader line_header; - status = ReadProfileLineHeader(fd, &line_header, error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - - status = ReadProfileLine(fd, line_header, error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - number_of_lines--; - } - - int result = testEOF(fd); - if (result == 0) { - return PROFILE_LOAD_SUCCESS; - } - - if (result < 0) { - return PROFILE_LOAD_IO_ERROR; - } - - *error = "Unexpected content in the profile file"; - return PROFILE_LOAD_BAD_DATA; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::ReadProfileHeader(int fd, uint32_t *number_of_lines, - PandaString *error) -{ - const size_t K_MAGIC_VERSION_SIZE = sizeof(kProfileMagic) + sizeof(kProfileVersion) + sizeof(uint32_t); - - SerializerBuffer safe_buffer(K_MAGIC_VERSION_SIZE); - - ProfileLoadSatus status = safe_buffer.FillFromFd(fd, "ReadProfileHeader", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - - if (!safe_buffer.CompareAndAdvance(kProfileMagic, sizeof(kProfileMagic))) { - *error = "Profile missing magic"; - return PROFILE_LOAD_VERSION_MISMATCH; - } - if (!safe_buffer.CompareAndAdvance(kProfileVersion, sizeof(kProfileVersion))) { - *error = "Profile version mismatch"; - return PROFILE_LOAD_VERSION_MISMATCH; - } - - *number_of_lines = safe_buffer.ReadUintAndAdvance(); - return PROFILE_LOAD_SUCCESS; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::ReadProfileLineHeader(int fd, ProfileLineHeader *line_header, - PandaString *error) -{ - SerializerBuffer header_buffer(K_LINE_HEADER_SIZE); - ProfileLoadSatus status = header_buffer.FillFromFd(fd, "ReadProfileLineHeader", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - - auto panda_location_size = header_buffer.ReadUintAndAdvance(); // max chars in location, 4096 = 2 ^ 12 - line_header->method_set_size = header_buffer.ReadUintAndAdvance(); - line_header->class_set_size = header_buffer.ReadUintAndAdvance(); - line_header->checksum = header_buffer.ReadUintAndAdvance(); - - if (panda_location_size == 0 || panda_location_size > K_MAX_FILE_KEY_LENGTH) { - *error = "PandaFileKey has an invalid size: " + std::to_string(panda_location_size); - return PROFILE_LOAD_BAD_DATA; - } - - SerializerBuffer location_buffer(panda_location_size); - // Read the binary data: location string - status = location_buffer.FillFromFd(fd, "ReadProfileLineHeader", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - line_header->panda_file_location.assign(reinterpret_cast(location_buffer.Get()), panda_location_size); - return PROFILE_LOAD_SUCCESS; -} - -ProfileDumpInfo::ProfileLoadSatus ProfileDumpInfo::ReadProfileLine(int fd, const ProfileLineHeader &line_header, - PandaString *error) -{ - static constexpr uint32_t K_MAX_NUMBER_OF_ENTRIES_TO_READ = 8000; // ~8 kb - uint32_t methods_left_to_read = line_header.method_set_size; - uint32_t classes_left_to_read = line_header.class_set_size; - - while ((methods_left_to_read > 0) || (classes_left_to_read > 0)) { - uint32_t methods_to_read = std::min(K_MAX_NUMBER_OF_ENTRIES_TO_READ, methods_left_to_read); - uint32_t max_classes_to_read = K_MAX_NUMBER_OF_ENTRIES_TO_READ - methods_to_read; // >=0 - uint32_t classes_to_read = std::min(max_classes_to_read, classes_left_to_read); - - size_t line_size = K_METHOD_BYTES * methods_to_read + K_CLASS_BYTES * classes_to_read; - SerializerBuffer line_buffer(line_size); - - ProfileLoadSatus status = line_buffer.FillFromFd(fd, "ReadProfileLine", error); - if (status != PROFILE_LOAD_SUCCESS) { - return status; - } - if (!ProcessLine(line_buffer, methods_to_read, classes_to_read, line_header.checksum, - line_header.panda_file_location)) { - *error = "Error when reading profile file line"; - return PROFILE_LOAD_BAD_DATA; - } - - methods_left_to_read -= methods_to_read; - classes_left_to_read -= classes_to_read; - } - return PROFILE_LOAD_SUCCESS; -} - -// NOLINTNEXTLINE(google-runtime-references) -bool ProfileDumpInfo::ProcessLine(SerializerBuffer &line_buffer, uint32_t method_set_size, uint32_t class_set_size, - uint32_t checksum, const PandaString &panda_file_location) -{ - for (uint32_t i = 0; i < method_set_size; i++) { - // NB! Read the method info from buffer... - auto method_idx = line_buffer.ReadUintAndAdvance(); - if (!AddMethodWrapper(panda_file_location, checksum, MethodWrapper(method_idx))) { - return false; - } - } - - for (uint32_t i = 0; i < class_set_size; i++) { - auto class_def_idx = line_buffer.ReadUintAndAdvance(); - if (!AddClassWrapper(panda_file_location, checksum, ClassWrapper(class_def_idx))) { - return false; - } - } - return true; -} - -bool ProfileDumpInfo::MergeAndSave(const PandaString &filename, uint64_t *bytes_written, bool force) -{ - // NB! we using READWRITE mode to leave the creation job to framework layer. - panda::os::unix::file::File myfile = panda::os::file::Open(filename, panda::os::file::Mode::READWRITE); - if (!myfile.IsValid()) { - LOG(ERROR, RUNTIME) << "Cannot open the profile file" << filename; - return false; - } - panda::os::file::FileHolder fholder(myfile); - int fd = myfile.GetFd(); - - LOG(INFO, RUNTIME) << " Step3.2: starting merging ***"; - PandaString error; - ProfileDumpInfo file_dump_info; - ProfileLoadSatus status = file_dump_info.LoadInternal(fd, &error); - if (status == PROFILE_LOAD_SUCCESS || status == PROFILE_LOAD_EMPTYFILE) { - if (MergeWith(file_dump_info)) { - if (dump_info_ == file_dump_info.dump_info_) { - if (bytes_written != nullptr) { - *bytes_written = 0; - } - LOG(INFO, RUNTIME) << " No Saving as no change byte_written = 0"; - if (status != PROFILE_LOAD_EMPTYFILE) { - return true; - } - } - } else { - LOG(INFO, RUNTIME) << " No Saving as Could not merge previous profile data from file " << filename; - if (!force) { - return false; - } - } - } else if (force && ((status == PROFILE_LOAD_VERSION_MISMATCH) || (status == PROFILE_LOAD_BAD_DATA))) { - LOG(INFO, RUNTIME) << " Clearing bad or mismatch version profile data from file " << filename << ": " << error; - } else { - LOG(INFO, RUNTIME) << " No Saving as Could not load profile data from file " << filename << ": " << error; - return false; - } - - LOG(INFO, RUNTIME) << " Step3.3: starting Saving ***"; - LOG(INFO, RUNTIME) << " clear file data firstly"; - if (!myfile.ClearData()) { - LOG(INFO, RUNTIME) << "Could not clear profile file: " << filename; - return false; - } - - bool result = Save(fd); - if (result) { - if (bytes_written != nullptr) { - LOG(INFO, RUNTIME) << " Profile Saver Bingo! and bytes written = " << bytes_written; - *bytes_written = GetFileSizeBytes(filename); - } - } else { - LOG(ERROR, RUNTIME) << "Failed to save profile info to " << filename; - } - return result; -} - -} // namespace panda diff --git a/runtime/profilesaver/profile_dump_info.h b/runtime/profilesaver/profile_dump_info.h deleted file mode 100644 index 61f2447188..0000000000 --- a/runtime/profilesaver/profile_dump_info.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PANDA_RUNTIME_PROFILESAVER_PROFILE_DUMP_INFO_H_ -#define PANDA_RUNTIME_PROFILESAVER_PROFILE_DUMP_INFO_H_ - -#include -#include -#include -#include -#include - -#include "libpandabase/utils/logger.h" -#include "libpandafile/file.h" -#include "runtime/include/mem/panda_containers.h" -#include "runtime/include/mem/panda_smart_pointers.h" -#include "runtime/include/mem/panda_string.h" - -// NB! suppose that, panda file can always provide such profile file format data! -// NB! we use serializer saving way which means the profile file is just binary file! -// profile header -// magic -// version -// checksum?(ommit) -// #lines -// Line1: -// profileline header -// file location -// #method -// #class -// checksum -// methods index/id(#method) -// class index/id(#class) -// LineN: -// ... - -namespace panda { - -/* - * Any newly added information, we have to change the following info naturely, especially - * ExtractedResolvedClasses - */ -struct ExtractedMethod { - ExtractedMethod(const panda_file::File *file, panda_file::File::EntityId file_id) - : panda_file_(file), file_id_(file_id) - { - } - const panda_file::File *panda_file_; // NOLINT(misc-non-private-member-variables-in-classes) - panda_file::File::EntityId file_id_; // NOLINT(misc-non-private-member-variables-in-classes) -}; - -struct ExtractedResolvedClasses { -public: - // NOLINTNEXTLINE(modernize-pass-by-value) - ExtractedResolvedClasses(const PandaString &location, uint32_t checksum) - : panda_file_location_(location), panda_file_checksum_(checksum) - { - } - - int Compare(const ExtractedResolvedClasses &other) const - { - if (panda_file_checksum_ != other.panda_file_checksum_) { - return static_cast(panda_file_checksum_ - other.panda_file_checksum_); - } - return panda_file_location_.compare(other.panda_file_location_); - } - - template - void AddClasses(InputIt begin, InputIt end) const - { - classes_.insert(begin, end); - } - - void AddClass(uint32_t classindex) const - { - classes_.insert(classindex); - } - - // NOLINTNEXTLINE(readability-const-return-type) - const PandaString GetPandaFileLocation() const - { - return panda_file_location_; - } - - uint32_t GetPandaFileChecksum() const - { - return panda_file_checksum_; - } - - const PandaUnorderedSet &GetClasses() const - { - return classes_; - } - -private: - const PandaString panda_file_location_; // NOLINT(readability-identifier-naming) - const uint32_t panda_file_checksum_; // NOLINT(readability-identifier-naming) - // Array of resolved class def indexes. we leave this as extention - mutable PandaUnorderedSet classes_; -}; - -// we define this for PandaSet find() function -inline bool operator<(const ExtractedResolvedClasses &a, const ExtractedResolvedClasses &b) -{ - return a.Compare(b) < 0; -} - -class ProfileDumpInfo { -public: - // Content of profile header - static const uint8_t kProfileMagic[]; // NOLINT(modernize-avoid-c-arrays, readability-identifier-naming) - static const uint8_t kProfileVersion[]; // NOLINT(modernize-avoid-c-arrays, readability-identifier-naming) - - /* - * Saves the profile data to the given file descriptor. - */ - bool Save(int fd); - - /* - * Loads profile information from the given file descriptor. - */ - bool Load(int fd); - - /* - * Merge the data from another ProfileDumpInfo into the current object. - */ - bool MergeWith(const ProfileDumpInfo &other); - - /* - * Add the given methods and classes to the current profile object - */ - bool AddMethodsAndClasses(const PandaVector &methods, - const PandaSet &resolved_classes); - - /* - * Loads and merges profile information from the given file into the current cache - * object and tries to save it back to disk. - * - * If `force` is true then the save will be forced regardless of bad data or mismatched version. - */ - bool MergeAndSave(const PandaString &filename, uint64_t *bytes_written, bool force); - - /* - * Returns the number of methods that were profiled. - */ - uint64_t GetNumberOfMethods() const; - - /* - * Returns the number of resolved classes that were profiled. - */ - uint64_t GetNumberOfResolvedClasses() const; - - /* - * Returns true if the method reference is present in the profiling info. - */ - bool ContainsMethod(const ExtractedMethod &method_ref) const; - - /* - * Returns true if the class is present in the profiling info. - */ - bool ContainsClass(const panda_file::File &pandafile, uint32_t class_def_idx) const; - -private: - enum ProfileLoadSatus { - PROFILE_LOAD_IO_ERROR, - PROFILE_LOAD_VERSION_MISMATCH, - PROFILE_LOAD_BAD_DATA, - PROFILE_LOAD_EMPTYFILE, - PROFILE_LOAD_SUCCESS - }; - - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) - struct ProfileLineHeader { - PandaString panda_file_location; - uint32_t method_set_size; - uint32_t class_set_size; - uint32_t checksum; - }; - - // A helper structure to make sure we don't read past our buffers in the loops. - struct SerializerBuffer { - public: - explicit SerializerBuffer(size_t size) - { - // NOLINTNEXTLINE(modernize-avoid-c-arrays) - storage_ = MakePandaUnique(size); - ptr_current_ = storage_.get(); - ptr_end_ = ptr_current_ + size; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic - } - - ProfileLoadSatus FillFromFd(int fd, const PandaString &source, PandaString *error); - - template - T ReadUintAndAdvance(); - - bool CompareAndAdvance(const uint8_t *data, size_t data_size); - - uint8_t *Get() - { - return storage_.get(); - } - - private: - PandaUniquePtr storage_; // NOLINT(modernize-avoid-c-arrays) - uint8_t *ptr_current_; - uint8_t *ptr_end_; - }; - - struct MethodWrapper { - explicit MethodWrapper(uint32_t index) : method_id_(index) {} - uint32_t method_id_; // NOLINT(misc-non-private-member-variables-in-classes) - - bool operator==(const MethodWrapper &other) const - { - return method_id_ == other.method_id_; - } - - bool operator<(const MethodWrapper &other) const - { - return method_id_ < other.method_id_; - } - }; - - struct ClassWrapper { - explicit ClassWrapper(uint32_t index) : class_id_(index) {} - uint32_t class_id_; // NOLINT(misc-non-private-member-variables-in-classes) - - bool operator==(const ClassWrapper &other) const - { - return class_id_ == other.class_id_; - } - - bool operator<(const ClassWrapper &other) const - { - return class_id_ < other.class_id_; - } - }; - - struct ProfileLineData { - explicit ProfileLineData(uint32_t file_checksum) : checksum(file_checksum) {} - uint32_t checksum; // NOLINT(misc-non-private-member-variables-in-classes) - PandaSet method_wrapper_set; // NOLINT(misc-non-private-member-variables-in-classes) - PandaSet class_wrapper_set; // NOLINT(misc-non-private-member-variables-in-classes) - - bool operator==(const ProfileLineData &other) const - { - return checksum == other.checksum && method_wrapper_set == other.method_wrapper_set && - class_wrapper_set == other.class_wrapper_set; - } - - // NOLINTNEXTLINE(readability-identifier-naming) - bool empty() const - { - return method_wrapper_set.empty() && class_wrapper_set.empty(); - } - }; - - ProfileLoadSatus LoadInternal(int fd, PandaString *error); - ProfileLoadSatus ReadProfileHeader(int fd, uint32_t *number_of_lines, PandaString *error); - ProfileLoadSatus ReadProfileLineHeader(int fd, ProfileLineHeader *line_header, PandaString *error); - ProfileLoadSatus ReadProfileLine(int fd, const ProfileLineHeader &line_header, PandaString *error); - // NOLINTNEXTLINE(google-runtime-references) - bool ProcessLine(SerializerBuffer &line_buffer, uint32_t method_set_size, uint32_t class_set_size, - uint32_t checksum, const PandaString &panda_file_location); - - bool AddMethodWrapper(const PandaString &panda_file_location, uint32_t checksum, - const MethodWrapper &method_to_add); - bool AddClassWrapper(const PandaString &panda_file_location, uint32_t checksum, const ClassWrapper &class_to_add); - bool AddResolvedClasses(const ExtractedResolvedClasses &classes); - ProfileLineData *GetOrAddProfileLineData(const PandaString &panda_file_location, uint32_t checksum); - - PandaMap dump_info_; -}; - -} // namespace panda - -#endif // PANDA_RUNTIME_PROFILESAVER_PROFILE_DUMP_INFO_H_ diff --git a/runtime/profilesaver/profile_saver.cpp b/runtime/profilesaver/profile_saver.cpp deleted file mode 100644 index 97c0231358..0000000000 --- a/runtime/profilesaver/profile_saver.cpp +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "runtime/profilesaver/profile_saver.h" - -#include -#include -#include - -#include "runtime/include/class_linker.h" -#include "runtime/include/runtime.h" -#include "runtime/jit/jit.h" -#include "trace/trace.h" - -namespace panda { - -ProfileSaver *ProfileSaver::instance = nullptr; -// NOLINTNEXTLINE(fuchsia-statically-constructed-objects) -std::thread ProfileSaver::profiler_saver_daemon_thread; - -static bool CheckLocationForCompilation(const PandaString &location) -{ - return !location.empty(); -} - -// NOLINTNEXTLINE(cppcoreguidelines-pro-type-member-init) -ProfileSaver::ProfileSaver(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_dir) - : shutting_down_(false) -{ - AddTrackedLocations(output_filename, code_paths, app_dir); -} - -// NB! it is the caller's responsibility to pass suitable output_filename, code_paths as well as app_data_dir. -void ProfileSaver::AddTrackedLocations(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir) -{ - auto it = tracked_pandafile_base_locations_.find(output_filename); - if (it == tracked_pandafile_base_locations_.end()) { - tracked_pandafile_base_locations_.insert( - std::make_pair(output_filename, PandaSet(code_paths.begin(), code_paths.end()))); - if (!app_data_dir.empty()) { - app_data_dirs_.insert(app_data_dir); - } - } else { - if (UNLIKELY(app_data_dirs_.count(app_data_dir) <= 0)) { - LOG(INFO, RUNTIME) << "Cannot find app dir, bad output filename"; - return; - } - it->second.insert(code_paths.begin(), code_paths.end()); - } -} - -void ProfileSaver::Start(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir) -{ - if (Runtime::GetCurrent() == nullptr) { - LOG(ERROR, RUNTIME) << "Runtime is nullptr"; - return; - } - - if (!Runtime::GetCurrent()->SaveProfileInfo()) { - LOG(ERROR, RUNTIME) << "ProfileSaver is forbidden"; - return; - } - - if (output_filename.empty()) { - LOG(ERROR, RUNTIME) << "Invalid output filename"; - return; - } - - PandaVector code_paths_to_profile; - for (const PandaString &location : code_paths) { - if (CheckLocationForCompilation(location)) { - code_paths_to_profile.push_back(location); - } - } - - if (code_paths_to_profile.empty()) { - LOG(INFO, RUNTIME) << "No code paths should be profiled."; - return; - } - - if (UNLIKELY(instance != nullptr)) { - LOG(INFO, RUNTIME) << "Profile Saver Singleton already exists"; - instance->AddTrackedLocations(output_filename, code_paths_to_profile, app_data_dir); - return; - } - - LOG(INFO, RUNTIME) << "Starting dumping profile saver output file" << output_filename; - - instance = new ProfileSaver(output_filename, code_paths_to_profile, app_data_dir); - profiler_saver_daemon_thread = std::thread(ProfileSaver::RunProfileSaverThread, reinterpret_cast(instance)); -} - -void ProfileSaver::Stop(bool dump_info) -{ - { - os::memory::LockHolder lock(profile_saver_lock_); - - if (instance == nullptr) { - LOG(ERROR, RUNTIME) << "Tried to stop a profile saver which was not started"; - return; - } - - if (instance->shutting_down_) { - LOG(ERROR, RUNTIME) << "Tried to stop the profile saver twice"; - return; - } - - instance->shutting_down_ = true; - - if (dump_info) { - instance->DumpInfo(); - } - } - - // Wait for the saver thread to stop. - // NB! we must release profile_saver_lock_ here. - profiler_saver_daemon_thread.join(); - - // Kill the singleton ... - delete instance; - instance = nullptr; -} - -bool ProfileSaver::IsStarted() -{ - return instance != nullptr; -} - -void ProfileSaver::DumpInfo() -{ - LOG(INFO, RUNTIME) << "ProfileSaver stopped" << '\n'; -} - -void *ProfileSaver::RunProfileSaverThread(void *arg) -{ - // NOLINTNEXTLINE(hicpp-use-auto, modernize-use-auto) - ProfileSaver *profile_saver = reinterpret_cast(arg); - profile_saver->Run(); - - LOG(INFO, RUNTIME) << "Profile saver shutdown"; - return nullptr; -} - -void ProfileSaver::Run() -{ - while (!ShuttingDown()) { - LOG(INFO, RUNTIME) << "Step1: Time Sleeping >>>>>>> "; - uint32_t sleepytime = Runtime::GetOptions().GetProfilesaverSleepingTimeMs(); - constexpr uint32_t TIME_SECONDS_IN_MS = 1000; - for (int i = 0; i < static_cast(sleepytime / TIME_SECONDS_IN_MS); ++i) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - if (ShuttingDown()) { - break; - } - } - - LOG(INFO, RUNTIME) << "Step2: tranverse the resolved class and methods >>>>>>> "; - TranverseAndCacheResolvedClassAndMethods(); - - LOG(INFO, RUNTIME) << "Step3: merge current profile file and save it back >>>>>>> "; - MergeAndDumpProfileData(); - } -} - -bool ProfileSaver::ShuttingDown() -{ - os::memory::LockHolder lock(profile_saver_lock_); - return shutting_down_; -} - -void ProfileSaver::TranverseAndCacheResolvedClassAndMethods() -{ - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - PandaSet resolved_classes; - PandaVector methods; - auto call_back = [&resolved_classes, &methods](Class *klass) -> bool { - const panda_file::File *pandafile = klass->GetPandaFile(); - panda_file::File::EntityId classfieldid = klass->GetFileId(); - - if (pandafile == nullptr) { - LOG(INFO, RUNTIME) << "panda file is nullptr"; - return false; - } - LOG(INFO, RUNTIME) << " pandafile name = " << pandafile->GetFilename() - << " classname = " << klass->GetName(); - - Span tmp_methods = klass->GetMethods(); - LOG(INFO, RUNTIME) << " methods size = " << tmp_methods.size(); - for (int i = 0; i < static_cast(tmp_methods.Size()); ++i) { - Method &method = tmp_methods[i]; - if (!method.IsNative()) { - if (method.GetHotnessCounter() >= K_MIN_PROFILE_THRESHOLD) { - ASSERT(method.GetPandaFile() != nullptr); - LOG(INFO, RUNTIME) << " method pandafile name = " << method.GetPandaFile()->GetFilename(); - methods.emplace_back(ExtractedMethod(method.GetPandaFile(), method.GetFileId())); - } - } - } - - ExtractedResolvedClasses tmp_resolved_classes(ConvertToString(pandafile->GetFilename()), - pandafile->GetHeader()->checksum); - LOG(INFO, RUNTIME) << " Add class " << klass->GetName(); - auto it = resolved_classes.find(tmp_resolved_classes); - if (it != resolved_classes.end()) { - it->AddClass(classfieldid.GetOffset()); - } else { - tmp_resolved_classes.AddClass(classfieldid.GetOffset()); - resolved_classes.insert(tmp_resolved_classes); - } - - return true; - }; - - // NB: classliner == nullptr - if (Runtime::GetCurrent()->GetClassLinker() == nullptr) { - LOG(INFO, RUNTIME) << "classliner is nullptr"; - return; - } - - LOG(INFO, RUNTIME) << " Step2.1: tranverse the resolved class and methods"; - Runtime::GetCurrent()->GetClassLinker()->EnumerateClasses(call_back); - LOG(INFO, RUNTIME) << " Step2.2: starting tracking all the pandafile locations and flush the cache"; - - for (const auto &it : tracked_pandafile_base_locations_) { - const PandaString &filename = it.first; - const PandaSet &locations = it.second; - - PandaSet resolved_classes_for_location; - PandaVector methods_for_location; - - LOG(INFO, RUNTIME) << " all the locations are:"; - for (auto const &iter : locations) { - LOG(INFO, RUNTIME) << iter << " "; - } - - LOG(INFO, RUNTIME) << " Methods name : "; - for (const ExtractedMethod &ref : methods) { - LOG(INFO, RUNTIME) << " " << ref.panda_file_->GetFilename(); - if (locations.find(ConvertToString(ref.panda_file_->GetFilename())) != locations.end()) { - LOG(INFO, RUNTIME) << " bingo method!"; - methods_for_location.push_back(ref); - } - } - LOG(INFO, RUNTIME) << std::endl; - LOG(INFO, RUNTIME) << " Classes name"; - - for (const ExtractedResolvedClasses &classes : resolved_classes) { - LOG(INFO, RUNTIME) << " " << classes.GetPandaFileLocation(); - if (locations.find(classes.GetPandaFileLocation()) != locations.end()) { - LOG(INFO, RUNTIME) << " bingo class!"; - resolved_classes_for_location.insert(classes); - } - } - - ProfileDumpInfo *info = GetOrAddCachedProfiledInfo(filename); - LOG(INFO, RUNTIME) << " Adding Bingo Methods and Classes"; - info->AddMethodsAndClasses(methods_for_location, resolved_classes_for_location); - } -} - -ProfileDumpInfo *ProfileSaver::GetOrAddCachedProfiledInfo(const PandaString &filename) -{ - auto info_it = profile_cache_.find(filename); - if (info_it == profile_cache_.end()) { - LOG(INFO, RUNTIME) << " bingo profile_cache_!"; - auto ret = profile_cache_.insert(std::make_pair(filename, ProfileDumpInfo())); - ASSERT(ret.second); - info_it = ret.first; - } - return &(info_it->second); -} - -ProfileSaver::CntStats *ProfileSaver::GetOrAddCachedProfiledStatsInfo(const PandaString &filename) -{ - auto info_it = statcache.find(filename); - if (info_it == statcache.end()) { - LOG(INFO, RUNTIME) << " bingo StatsInfo_cache_!"; - auto ret = statcache.insert(std::make_pair(filename, CntStats())); - ASSERT(ret.second); - info_it = ret.first; - } - return &(info_it->second); -} - -void ProfileSaver::MergeAndDumpProfileData() -{ - trace::ScopedTrace scoped_trace(__PRETTY_FUNCTION__); - for (const auto &it : tracked_pandafile_base_locations_) { - if (ShuttingDown()) { - return; - } - const PandaString &filename = it.first; - LOG(INFO, RUNTIME) << " Step3.1 starting merging and save the following file ***"; - LOG(INFO, RUNTIME) << " filename = " << filename; - - ProfileDumpInfo *cached_info = GetOrAddCachedProfiledInfo(filename); - CntStats *cached_stat = GetOrAddCachedProfiledStatsInfo(filename); - ASSERT(cached_info->GetNumberOfMethods() >= cached_stat->GetMethodCount()); - ASSERT(cached_info->GetNumberOfResolvedClasses() >= cached_stat->GetClassCount()); - uint64_t delta_number_of_methods = cached_info->GetNumberOfMethods() - cached_stat->GetMethodCount(); - uint64_t delta_number_of_classes = cached_info->GetNumberOfResolvedClasses() - cached_stat->GetClassCount(); - uint64_t numthreshold = Runtime::GetOptions().GetProfilesaverDeltaNumberThreshold(); - if (delta_number_of_methods < numthreshold && delta_number_of_classes < numthreshold) { - LOG(INFO, RUNTIME) << " number of delta number/class not enough"; - continue; - } - - uint64_t bytes_written; - if (cached_info->MergeAndSave(filename, &bytes_written, true)) { - cached_stat->SetMethodCount(cached_info->GetNumberOfMethods()); - cached_stat->SetClassCount(cached_info->GetNumberOfResolvedClasses()); - } else { - LOG(INFO, RUNTIME) << "Could not save profiling info to " << filename; - } - } -} - -} // namespace panda diff --git a/runtime/profilesaver/profile_saver.h b/runtime/profilesaver/profile_saver.h deleted file mode 100644 index b3f38ee834..0000000000 --- a/runtime/profilesaver/profile_saver.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PANDA_RUNTIME_PROFILESAVER_PROFILE_SAVER_H_ -#define PANDA_RUNTIME_PROFILESAVER_PROFILE_SAVER_H_ - -#include - -#include -#include -#include -#include -#include - -#include "libpandabase/macros.h" -#include "libpandabase/os/mutex.h" -#include "libpandabase/utils/logger.h" -#include "runtime/include/mem/panda_containers.h" -#include "runtime/include/mem/panda_string.h" -#include "runtime/profilesaver/profile_dump_info.h" - -namespace panda { - -// NOLINTNEXTLINE(fuchsia-statically-constructed-objects, readability-identifier-naming) -static os::memory::Mutex profile_saver_lock_; - -/* - * Note well! we take singleton pattern, multi-threading scenario should be taken more serious considerations. - * - * e.g. Global Mutex Management or corresponding alternatives should better than - * global mutex profile_saver_lock_. - * - */ - -// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) -class ProfileSaver { -public: - /* - * start the profile saver deamon thread - * - * output_filename records the profile name, code_paths stores all the locations contain pandafile(aka *.aex) - * app_data_dir contains the location of application package - */ - static void Start(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir); - - /* - * stop the profile saver deamon thread. - * - * if dump_info == true, dumps the debug information - */ - static void Stop(bool dump_info); - - /* - * whether profile saver instance exists. - */ - static bool IsStarted(); - - ~ProfileSaver() = default; - -private: - ProfileSaver(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_dir); - - void AddTrackedLocations(const PandaString &output_filename, const PandaVector &code_paths, - const PandaString &app_data_dir); - - /* - * Callback for pthread_create, we attach/detach this thread to Runtime here - */ - static void *RunProfileSaverThread(void *arg); - - /* - * Run loop for the saver. - */ - void Run(); - - /* - * Returns true if the saver is shutting down (ProfileSaver::Stop() has been called, will set this flag). - */ - bool ShuttingDown(); - - /* - * Dump functions, we leave it stub and for test until now. - */ - void DumpInfo(); - - /* - * Fetches the current resolved classes and methods from the ClassLinker and stores them in the profile_cache_. - */ - void TranverseAndCacheResolvedClassAndMethods(); - - /* - * Retrieves the cached ProfileDumpInfo for the given profile filename. - * If no entry exists, a new empty one will be created, added to the cache and then returned. - */ - ProfileDumpInfo *GetOrAddCachedProfiledInfo(const PandaString &filename); - - /* - * Processes the existing profiling info from the jit code cache(if exists) and returns - * true if it needed to be saved back to disk. - */ - void MergeAndDumpProfileData(); - - static ProfileSaver *instance; - - static std::thread profiler_saver_daemon_thread; - - PandaMap> tracked_pandafile_base_locations_; - - PandaMap profile_cache_; - - PandaSet app_data_dirs_; - - bool shutting_down_ GUARDED_BY(profile_saver_lock_); - - struct CntStats { - public: - uint64_t GetMethodCount() - { - return last_save_number_of_methods_; - } - - void SetMethodCount(uint64_t methodcnt) - { - last_save_number_of_methods_ = methodcnt; - } - - uint64_t GetClassCount() - { - return last_save_number_of_classes_; - } - - void SetClassCount(uint64_t classcnt) - { - last_save_number_of_classes_ = classcnt; - } - - private: - uint64_t last_save_number_of_methods_ {0}; - uint64_t last_save_number_of_classes_ {0}; - }; - - PandaMap statcache; // NOLINT(readability-identifier-naming) - - /* - * Retrieves the cached CntStats for the given profile filename. - * If no entry exists, a new empty one will be created, added to the cache and then returned. - */ - CntStats *GetOrAddCachedProfiledStatsInfo(const PandaString &filename); - - NO_COPY_SEMANTIC(ProfileSaver); - NO_MOVE_SEMANTIC(ProfileSaver); -}; - -} // namespace panda - -#endif // PANDA_RUNTIME_PROFILESAVER_PROFILE_SAVER_H_ diff --git a/runtime/runtime.cpp b/runtime/runtime.cpp index 95385690d5..a96346064f 100644 --- a/runtime/runtime.cpp +++ b/runtime/runtime.cpp @@ -58,7 +58,6 @@ #include "runtime/mem/internal_allocator-inl.h" #include "runtime/core/core_class_linker_extension.h" #include "runtime/include/panda_vm.h" -#include "runtime/profilesaver/profile_saver.h" #include "runtime/tooling/debugger.h" #include "runtime/tooling/pt_lang_ext_private.h" #include "runtime/include/file_manager.h" @@ -307,12 +306,6 @@ bool Runtime::Destroy() trace::ScopedTrace scoped_trace("Runtime shutdown"); instance->GetPandaVM()->StopGC(); - // NB! stop the profile saver thread before deleting the thread list to avoid dead loop here. - // the following WaitForThreadStop makes sure profile saver can be shut down. - if (instance->SaveProfileInfo()) { - ProfileSaver::Stop(false); - } - instance->GetPandaVM()->UninitializeThreads(); verifier::JobQueue::Stop(instance->GetVerificationOptions().Mode.OnlyVerify); @@ -883,9 +876,6 @@ void Runtime::RegisterAppInfo(const PandaVector &code_paths, const }(profile_output_filename); StartDProfiler(app_name); - - // this is exactly the place where start the profile saver - ProfileSaver::Start(profile_output_filename, code_paths, PandaString(app_name)); } int Runtime::StartDProfiler(std::string_view app_name) -- Gitee