From c9b55de1ba20b64dac3ae690cf15ffa062cb9de4 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Fri, 20 Mar 2020 16:34:22 -0700 Subject: libperfmgr: allow hints placed before NodeLooperThread starts Also add dumps for active request/hint per node Bug: 147840817 Test: boost flame Test: adb shell /data/nativetest64/libperfmgr_test/libperfmgr_test Change-Id: I4898101f5c8a8d1c69de2caf9ad6f5b4a106f6c6 --- libperfmgr/FileNode.cc | 18 ++++++---- libperfmgr/HintManager.cc | 19 +++++----- libperfmgr/Node.cc | 9 ++--- libperfmgr/NodeLooperThread.cc | 8 ++--- libperfmgr/PropertyNode.cc | 17 ++++----- libperfmgr/RequestGroup.cc | 20 +++++++++++ libperfmgr/include/perfmgr/FileNode.h | 4 +-- libperfmgr/include/perfmgr/Node.h | 9 ++--- libperfmgr/include/perfmgr/NodeLooperThread.h | 4 +-- libperfmgr/include/perfmgr/RequestGroup.h | 2 ++ libperfmgr/tests/FileNodeTest.cc | 11 +++--- libperfmgr/tests/HintManagerTest.cc | 50 +++++++++++++++++++++------ libperfmgr/tests/NodeLooperThreadTest.cc | 7 ++-- libperfmgr/tests/PropertyNodeTest.cc | 11 +++--- libperfmgr/tests/RequestGroupTest.cc | 4 +-- libperfmgr/tools/ConfigVerifier.cc | 17 +++++---- 16 files changed, 135 insertions(+), 75 deletions(-) diff --git a/libperfmgr/FileNode.cc b/libperfmgr/FileNode.cc index 060b3090..4133f0a8 100644 --- a/libperfmgr/FileNode.cc +++ b/libperfmgr/FileNode.cc @@ -16,6 +16,8 @@ #define LOG_TAG "libperfmgr" +#include "perfmgr/FileNode.h" + #include #include #include @@ -23,8 +25,6 @@ #include #include -#include "perfmgr/FileNode.h" - namespace android { namespace perfmgr { @@ -34,10 +34,9 @@ FileNode::FileNode(std::string name, std::string node_path, bool hold_fd) : Node(std::move(name), std::move(node_path), std::move(req_sorted), default_val_index, reset_on_init), - hold_fd_(hold_fd), warn_timeout_(android::base::GetBoolProperty("ro.debuggable", false) ? 5ms : 50ms) { - if (reset_on_init) { - Update(false); - } + hold_fd_(hold_fd), + warn_timeout_( + android::base::GetBoolProperty("ro.debuggable", false) ? 5ms : 50ms) { } std::chrono::milliseconds FileNode::Update(bool log_error) { @@ -53,7 +52,7 @@ std::chrono::milliseconds FileNode::Update(bool log_error) { } // Update node only if request index changes - if (value_index != current_val_index_) { + if (value_index != current_val_index_ || reset_on_init_) { const std::string& req_value = req_sorted_[value_index].GetRequestValue(); @@ -87,6 +86,7 @@ std::chrono::milliseconds FileNode::Update(bool log_error) { } // Update current index only when succeed current_val_index_ = value_index; + reset_on_init_ = false; } } return expire_time; @@ -108,6 +108,10 @@ void FileNode::DumpToFd(int fd) const { if (!android::base::WriteStringToFd(buf, fd)) { LOG(ERROR) << "Failed to dump fd: " << fd; } + for (std::size_t i = 0; i < req_sorted_.size(); i++) { + req_sorted_[i].DumpToFd( + fd, android::base::StringPrintf("\t\tReq%zu:\t", i)); + } } } // namespace perfmgr diff --git a/libperfmgr/HintManager.cc b/libperfmgr/HintManager.cc index 13060b01..1b546ae6 100644 --- a/libperfmgr/HintManager.cc +++ b/libperfmgr/HintManager.cc @@ -16,17 +16,17 @@ #define LOG_TAG "libperfmgr" -#include -#include +#include "perfmgr/HintManager.h" #include #include - #include #include +#include +#include + #include "perfmgr/FileNode.h" -#include "perfmgr/HintManager.h" #include "perfmgr/PropertyNode.h" namespace android { @@ -217,13 +217,14 @@ std::vector> HintManager::ParseNodes( LOG(VERBOSE) << "Node[" << i << "]'s Value[" << j << "]: " << value; auto result = values_set_parsed.insert(value); if (!result.second) { - LOG(ERROR) << "Duplicate value parsed in Node[" << i << "]'s Value[" << j - << "]"; + LOG(ERROR) << "Duplicate value parsed in Node[" << i + << "]'s Value[" << j << "]"; nodes_parsed.clear(); return nodes_parsed; } if (is_file && value.empty()) { - LOG(ERROR) << "Failed to read Node[" << i << "]'s Value[" << j << "]"; + LOG(ERROR) << "Failed to read Node[" << i << "]'s Value[" << j + << "]"; nodes_parsed.clear(); return nodes_parsed; } @@ -326,8 +327,8 @@ std::map> HintManager::ParseActions( if (nodes_index.find(node_name) == nodes_index.end()) { LOG(ERROR) << "Failed to find " - << "Action[" << i - << "]'s Node from Nodes section: [" << node_name << "]"; + << "Action[" << i << "]'s Node from Nodes section: [" + << node_name << "]"; actions_parsed.clear(); return actions_parsed; } diff --git a/libperfmgr/Node.cc b/libperfmgr/Node.cc index 8c13dae4..eb180e65 100644 --- a/libperfmgr/Node.cc +++ b/libperfmgr/Node.cc @@ -16,13 +16,13 @@ #define LOG_TAG "libperfmgr" +#include "perfmgr/Node.h" + #include #include #include #include -#include "perfmgr/Node.h" - namespace android { namespace perfmgr { @@ -34,10 +34,7 @@ Node::Node(std::string name, std::string node_path, req_sorted_(std::move(req_sorted)), default_val_index_(default_val_index), reset_on_init_(reset_on_init), - // Assigning an invalid value so the next Update() will update the - // Node's value to default - current_val_index_(reset_on_init ? req_sorted_.size() - : default_val_index) {} + current_val_index_(default_val_index) {} bool Node::AddRequest(std::size_t value_index, const std::string& hint_type, ReqTime end_time) { diff --git a/libperfmgr/NodeLooperThread.cc b/libperfmgr/NodeLooperThread.cc index 9bb10c0b..747cd319 100644 --- a/libperfmgr/NodeLooperThread.cc +++ b/libperfmgr/NodeLooperThread.cc @@ -16,11 +16,11 @@ #define LOG_TAG "libperfmgr" +#include "perfmgr/NodeLooperThread.h" + #include #include -#include "perfmgr/NodeLooperThread.h" - namespace android { namespace perfmgr { @@ -31,7 +31,7 @@ bool NodeLooperThread::Request(const std::vector& actions, return false; } if (!::android::Thread::isRunning()) { - LOG(FATAL) << "NodeLooperThread stopped, abort..."; + LOG(WARNING) << "NodeLooperThread is not running, request " << hint_type; } bool ret = true; @@ -70,7 +70,7 @@ bool NodeLooperThread::Cancel(const std::vector& actions, return false; } if (!::android::Thread::isRunning()) { - LOG(FATAL) << "NodeLooperThread stopped, abort..."; + LOG(WARNING) << "NodeLooperThread is not running, cancel " << hint_type; } bool ret = true; diff --git a/libperfmgr/PropertyNode.cc b/libperfmgr/PropertyNode.cc index 029849d6..c8067117 100644 --- a/libperfmgr/PropertyNode.cc +++ b/libperfmgr/PropertyNode.cc @@ -16,14 +16,14 @@ #define LOG_TAG "libperfmgr" +#include "perfmgr/PropertyNode.h" + #include #include #include #include #include -#include "perfmgr/PropertyNode.h" - namespace android { namespace perfmgr { @@ -31,11 +31,7 @@ PropertyNode::PropertyNode(std::string name, std::string node_path, std::vector req_sorted, std::size_t default_val_index, bool reset_on_init) : Node(std::move(name), std::move(node_path), std::move(req_sorted), - default_val_index, reset_on_init) { - if (reset_on_init) { - Update(false); - } -} + default_val_index, reset_on_init) {} std::chrono::milliseconds PropertyNode::Update(bool) { std::size_t value_index = default_val_index_; @@ -50,7 +46,7 @@ std::chrono::milliseconds PropertyNode::Update(bool) { } // Update node only if request index changes - if (value_index != current_val_index_) { + if (value_index != current_val_index_ || reset_on_init_) { const std::string& req_value = req_sorted_[value_index].GetRequestValue(); @@ -60,6 +56,7 @@ std::chrono::milliseconds PropertyNode::Update(bool) { } else { // Update current index only when succeed current_val_index_ = value_index; + reset_on_init_ = false; } } return expire_time; @@ -73,6 +70,10 @@ void PropertyNode::DumpToFd(int fd) const { if (!android::base::WriteStringToFd(buf, fd)) { LOG(ERROR) << "Failed to dump fd: " << fd; } + for (std::size_t i = 0; i < req_sorted_.size(); i++) { + req_sorted_[i].DumpToFd( + fd, android::base::StringPrintf("\t\tReq%zu:\t", i)); + } } } // namespace perfmgr diff --git a/libperfmgr/RequestGroup.cc b/libperfmgr/RequestGroup.cc index 857d17a4..4fedd33a 100644 --- a/libperfmgr/RequestGroup.cc +++ b/libperfmgr/RequestGroup.cc @@ -18,6 +18,11 @@ #include "perfmgr/RequestGroup.h" +#include +#include + +#include + namespace android { namespace perfmgr { @@ -60,5 +65,20 @@ bool RequestGroup::GetExpireTime(std::chrono::milliseconds* expire_time) { return active; } +void RequestGroup::DumpToFd(int fd, const std::string& prefix) const { + std::ostringstream dump_buf; + ReqTime now = std::chrono::steady_clock::now(); + for (auto it = request_map_.begin(); it != request_map_.end(); it++) { + auto remaining_duration = + std::chrono::duration_cast(it->second - + now); + dump_buf << prefix << it->first << "\t" << remaining_duration.count() + << "\t" << request_value_ << "\n"; + } + if (!android::base::WriteStringToFd(dump_buf.str(), fd)) { + LOG(ERROR) << "Failed to dump fd: " << fd; + } +} + } // namespace perfmgr } // namespace android diff --git a/libperfmgr/include/perfmgr/FileNode.h b/libperfmgr/include/perfmgr/FileNode.h index 34dbfc0c..b8f2db6e 100644 --- a/libperfmgr/include/perfmgr/FileNode.h +++ b/libperfmgr/include/perfmgr/FileNode.h @@ -17,12 +17,12 @@ #ifndef ANDROID_LIBPERFMGR_FILENODE_H_ #define ANDROID_LIBPERFMGR_FILENODE_H_ +#include + #include #include #include -#include - #include "perfmgr/Node.h" namespace android { diff --git a/libperfmgr/include/perfmgr/Node.h b/libperfmgr/include/perfmgr/Node.h index cd0fba82..e0db0777 100644 --- a/libperfmgr/include/perfmgr/Node.h +++ b/libperfmgr/include/perfmgr/Node.h @@ -17,12 +17,12 @@ #ifndef ANDROID_LIBPERFMGR_NODE_H_ #define ANDROID_LIBPERFMGR_NODE_H_ +#include + #include #include #include -#include - #include "perfmgr/RequestGroup.h" namespace android { @@ -78,10 +78,11 @@ class Node { const std::string name_; const std::string node_path_; - // request vector, one entry per possible value, sorted by priority + // request vector, one entry per possible value, sorted by priority. std::vector req_sorted_; const std::size_t default_val_index_; - const bool reset_on_init_; + // node will be explicitly initialized when first time called Update(). + bool reset_on_init_; std::size_t current_val_index_; }; diff --git a/libperfmgr/include/perfmgr/NodeLooperThread.h b/libperfmgr/include/perfmgr/NodeLooperThread.h index 981e64f2..eba0fc7f 100644 --- a/libperfmgr/include/perfmgr/NodeLooperThread.h +++ b/libperfmgr/include/perfmgr/NodeLooperThread.h @@ -17,14 +17,14 @@ #ifndef ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_ #define ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_ +#include + #include #include #include #include #include -#include - #include "perfmgr/Node.h" namespace android { diff --git a/libperfmgr/include/perfmgr/RequestGroup.h b/libperfmgr/include/perfmgr/RequestGroup.h index 2d997b59..698a8216 100644 --- a/libperfmgr/include/perfmgr/RequestGroup.h +++ b/libperfmgr/include/perfmgr/RequestGroup.h @@ -53,6 +53,8 @@ class RequestGroup { // hint_type. If request exits and the new end_time is less than the active // time, expire time will not be updated; also returns false. bool RemoveRequest(const std::string& hint_type); + // Dump internal status to fd + void DumpToFd(int fd, const std::string& prefix) const; private: const std::string request_value_; diff --git a/libperfmgr/tests/FileNodeTest.cc b/libperfmgr/tests/FileNodeTest.cc index 04d7345b..d163be80 100644 --- a/libperfmgr/tests/FileNodeTest.cc +++ b/libperfmgr/tests/FileNodeTest.cc @@ -14,14 +14,13 @@ * limitations under the License. */ -#include -#include - #include #include - #include +#include +#include + #include "perfmgr/FileNode.h" namespace android { @@ -43,6 +42,7 @@ static inline void _VerifyPathValue(const std::string& path, TEST(FileNodeTest, NoInitDefaultTest) { TemporaryFile tf; FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1, false); + t.Update(false); _VerifyPathValue(tf.path, ""); } @@ -50,9 +50,11 @@ TEST(FileNodeTest, NoInitDefaultTest) { TEST(FileNodeTest, InitDefaultTest) { TemporaryFile tf; FileNode t("t", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1, true); + t.Update(false); _VerifyPathValue(tf.path, "value1"); TemporaryFile tf2; FileNode t2("t2", tf2.path, {{"value0"}, {"value1"}, {"value2"}}, 0, true); + t2.Update(false); _VerifyPathValue(tf2.path, "value0"); } @@ -61,6 +63,7 @@ TEST(FileNodeTest, DumpToFdTest) { TemporaryFile tf; FileNode t("test_dump", tf.path, {{"value0"}, {"value1"}, {"value2"}}, 1, true); + t.Update(false); TemporaryFile dumptf; t.DumpToFd(dumptf.fd); fsync(dumptf.fd); diff --git a/libperfmgr/tests/HintManagerTest.cc b/libperfmgr/tests/HintManagerTest.cc index 3323a27b..a4d31884 100644 --- a/libperfmgr/tests/HintManagerTest.cc +++ b/libperfmgr/tests/HintManagerTest.cc @@ -14,15 +14,15 @@ * limitations under the License. */ -#include -#include - #include #include #include - +#include #include +#include +#include + #include "perfmgr/FileNode.h" #include "perfmgr/HintManager.h" #include "perfmgr/PropertyNode.h" @@ -220,7 +220,7 @@ TEST_F(HintManagerTest, HintInitDefaultTest) { EXPECT_TRUE(hm.IsRunning()); _VerifyPathValue(files_[0]->path, ""); _VerifyPathValue(files_[1]->path, "n1_value2"); - _VerifyPropertyValue(prop_, ""); + _VerifyPropertyValue(prop_, "n2_value2"); } // Test IsHintSupported @@ -231,6 +231,35 @@ TEST_F(HintManagerTest, HintSupportedTest) { EXPECT_FALSE(hm.IsHintSupported("NO_SUCH_HINT")); } +// Test DumpToFd +TEST_F(HintManagerTest, DumpToFdTest) { + HintManager hm(nm_, actions_); + TemporaryFile dumptf; + hm.DumpToFd(dumptf.fd); + fsync(dumptf.fd); + std::ostringstream dump_buf; + dump_buf << "========== Begin perfmgr nodes ==========\nNode Name\tNode " + "Path\tCurrent Index\tCurrent Value\nn0\t" + << files_[0]->path << "\t2\t\nn1\t" << files_[1]->path + << "\t2\t\nn2\tvendor.pwhal.mode\t2\t\n========== End perfmgr " + "nodes ==========\n"; + _VerifyPathValue(dumptf.path, dump_buf.str()); + TemporaryFile dumptf_started; + EXPECT_TRUE(hm.Start()); + std::this_thread::sleep_for(kSLEEP_TOLERANCE_MS); + EXPECT_TRUE(hm.IsRunning()); + hm.DumpToFd(dumptf_started.fd); + fsync(dumptf_started.fd); + dump_buf.str(""); + dump_buf.clear(); + dump_buf << "========== Begin perfmgr nodes ==========\nNode Name\tNode " + "Path\tCurrent Index\tCurrent Value\nn0\t" + << files_[0]->path << "\t2\t\nn1\t" << files_[1]->path + << "\t2\tn1_value2\nn2\tvendor.pwhal.mode\t2\tn2_value2\n=========" + "= End perfmgr nodes ==========\n"; + _VerifyPathValue(dumptf_started.path, dump_buf.str()); +} + // Test hint/cancel/expire with dummy actions TEST_F(HintManagerTest, HintTest) { HintManager hm(nm_, actions_); @@ -345,7 +374,7 @@ TEST_F(HintManagerTest, ParseFileNodesDuplicateValueTest) { size_t start_pos = json_doc_.find(from); json_doc_.replace(start_pos, from.length(), "1134000"); std::vector> nodes = - HintManager::ParseNodes(json_doc_); + HintManager::ParseNodes(json_doc_); EXPECT_EQ(0u, nodes.size()); } @@ -355,7 +384,7 @@ TEST_F(HintManagerTest, ParsePropertyNodesDuplicateValueTest) { size_t start_pos = json_doc_.find(from); json_doc_.replace(start_pos, from.length(), "LOW"); std::vector> nodes = - HintManager::ParseNodes(json_doc_); + HintManager::ParseNodes(json_doc_); EXPECT_EQ(0u, nodes.size()); } @@ -365,7 +394,7 @@ TEST_F(HintManagerTest, ParseFileNodesEmptyValueTest) { size_t start_pos = json_doc_.find(from); json_doc_.replace(start_pos, from.length(), ""); std::vector> nodes = - HintManager::ParseNodes(json_doc_); + HintManager::ParseNodes(json_doc_); EXPECT_EQ(0u, nodes.size()); } @@ -375,7 +404,7 @@ TEST_F(HintManagerTest, ParsePropertyNodesEmptyValueTest) { size_t start_pos = json_doc_.find(from); json_doc_.replace(start_pos, from.length(), ""); std::vector> nodes = - HintManager::ParseNodes(json_doc_); + HintManager::ParseNodes(json_doc_); EXPECT_EQ(3u, nodes.size()); EXPECT_EQ("CPUCluster0MinFreq", nodes[0]->GetName()); EXPECT_EQ("CPUCluster1MinFreq", nodes[1]->GetName()); @@ -497,7 +526,8 @@ TEST_F(HintManagerTest, GetFromJSONTest) { TemporaryFile json_file; ASSERT_TRUE(android::base::WriteStringToFile(json_doc_, json_file.path)) << strerror(errno); - std::unique_ptr hm = HintManager::GetFromJSON(json_file.path, false); + std::unique_ptr hm = + HintManager::GetFromJSON(json_file.path, false); EXPECT_NE(nullptr, hm.get()); EXPECT_FALSE(hm->IsRunning()); EXPECT_TRUE(hm->Start()); diff --git a/libperfmgr/tests/NodeLooperThreadTest.cc b/libperfmgr/tests/NodeLooperThreadTest.cc index 5683d117..9283d9f9 100644 --- a/libperfmgr/tests/NodeLooperThreadTest.cc +++ b/libperfmgr/tests/NodeLooperThreadTest.cc @@ -14,13 +14,12 @@ * limitations under the License. */ -#include -#include - #include - #include +#include +#include + #include "perfmgr/FileNode.h" #include "perfmgr/NodeLooperThread.h" diff --git a/libperfmgr/tests/PropertyNodeTest.cc b/libperfmgr/tests/PropertyNodeTest.cc index 1d1e332b..73f41c56 100644 --- a/libperfmgr/tests/PropertyNodeTest.cc +++ b/libperfmgr/tests/PropertyNodeTest.cc @@ -14,15 +14,14 @@ * limitations under the License. */ -#include -#include - #include #include #include - #include +#include +#include + #include "perfmgr/PropertyNode.h" namespace android { @@ -49,6 +48,7 @@ static inline const std::string _InitProperty(const std::string& path) { TEST(PropertyNodeTest, NoInitDefaultTest) { std::string key = _InitProperty("test.libperfmgr.key"); PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 1, false); + t.Update(false); _VerifyPropertyValue(key, ""); } @@ -56,9 +56,11 @@ TEST(PropertyNodeTest, NoInitDefaultTest) { TEST(PropertyNodeTest, InitDefaultTest) { std::string key = _InitProperty("test.libperfmgr.key"); PropertyNode t("t", key, {{"value0"}, {"value1"}, {"value2"}}, 1, true); + t.Update(false); _VerifyPropertyValue(key, "value1"); std::string key2 = _InitProperty("test.libperfmgr.key2"); PropertyNode t2("t2", key2, {{"value0"}, {"value1"}, {"value2"}}, 0, true); + t2.Update(false); _VerifyPropertyValue(key2, "value0"); } @@ -67,6 +69,7 @@ TEST(PropertyNodeTest, DumpToFdTest) { std::string key = _InitProperty("test.libperfmgr.key"); PropertyNode t("test_dump", key, {{"value0"}, {"value1"}, {"value2"}}, 1, true); + t.Update(false); TemporaryFile dumptf; t.DumpToFd(dumptf.fd); fsync(dumptf.fd); diff --git a/libperfmgr/tests/RequestGroupTest.cc b/libperfmgr/tests/RequestGroupTest.cc index 87bfa33c..f3393c80 100644 --- a/libperfmgr/tests/RequestGroupTest.cc +++ b/libperfmgr/tests/RequestGroupTest.cc @@ -14,11 +14,11 @@ * limitations under the License. */ +#include + #include #include -#include - #include "perfmgr/RequestGroup.h" namespace android { diff --git a/libperfmgr/tools/ConfigVerifier.cc b/libperfmgr/tools/ConfigVerifier.cc index 2e25e950..ad959102 100644 --- a/libperfmgr/tools/ConfigVerifier.cc +++ b/libperfmgr/tools/ConfigVerifier.cc @@ -14,14 +14,13 @@ * limitations under the License. */ -#include - -#include -#include - #include #include +#include #include +#include + +#include #include "perfmgr/HintManager.h" @@ -83,7 +82,8 @@ static void printUsage(const char* exec_name) { LOG(INFO) << usage; } -static void execConfig(const std::string& json_file, const std::string& hint_name, unsigned long hint_duration) { +static void execConfig(const std::string& json_file, + const std::string& hint_name, uint64_t hint_duration) { std::unique_ptr hm = android::perfmgr::HintManager::GetFromJSON(json_file); if (!hm.get() || !hm->IsRunning()) { @@ -91,8 +91,7 @@ static void execConfig(const std::string& json_file, const std::string& hint_nam } std::vector hints = hm->GetHints(); for (const auto& hint : hints) { - if (!hint_name.empty() && hint_name != hint) - continue; + if (!hint_name.empty() && hint_name != hint) continue; LOG(INFO) << "Do hint: " << hint; hm->DoHint(hint, std::chrono::milliseconds(hint_duration)); std::this_thread::yield(); @@ -113,7 +112,7 @@ int main(int argc, char* argv[]) { std::string config_path; std::string hint_name; bool exec_hint = false; - unsigned long hint_duration = 100; + uint64_t hint_duration = 100; while (true) { static struct option opts[] = { -- cgit v1.2.3