1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "BtStopWatch" 18 19 #include "common/stop_watch.h" 20 21 #include <iomanip> 22 #include <mutex> 23 #include <sstream> 24 #include <utility> 25 26 #include "common/init_flags.h" 27 #include "os/log.h" 28 29 namespace bluetooth { 30 namespace common { 31 32 static const int LOG_BUFFER_LENGTH = 10; 33 static std::array<StopWatchLog, LOG_BUFFER_LENGTH> stopwatch_logs; 34 static int current_buffer_index; 35 static std::recursive_mutex stopwatch_log_mutex; 36 37 void StopWatch::RecordLog(StopWatchLog log) { 38 std::unique_lock<std::recursive_mutex> lock(stopwatch_log_mutex, std::defer_lock); 39 if (!lock.try_lock()) { 40 LOG_INFO("try_lock fail. log content: %s, took %zu us", log.message.c_str(), 41 static_cast<size_t>( 42 std::chrono::duration_cast<std::chrono::microseconds>( 43 stopwatch_logs[current_buffer_index].end_timestamp - 44 stopwatch_logs[current_buffer_index].start_timestamp) 45 .count())); 46 return; 47 } 48 if (current_buffer_index >= LOG_BUFFER_LENGTH) { 49 current_buffer_index = 0; 50 } 51 stopwatch_logs[current_buffer_index] = std::move(log); 52 current_buffer_index++; 53 lock.unlock(); 54 } 55 56 void StopWatch::DumpStopWatchLog() { 57 std::lock_guard<std::recursive_mutex> lock(stopwatch_log_mutex); 58 LOG_INFO("====================================="); 59 LOG_INFO("bluetooth stopwatch log history:"); 60 for (int i = 0; i < LOG_BUFFER_LENGTH; i++) { 61 if (current_buffer_index >= LOG_BUFFER_LENGTH) { 62 current_buffer_index = 0; 63 } 64 if (stopwatch_logs[current_buffer_index].message.empty()) { 65 current_buffer_index++; 66 continue; 67 } 68 std::stringstream ss; 69 auto now = stopwatch_logs[current_buffer_index].timestamp; 70 auto millis = std::chrono::duration_cast<std::chrono::milliseconds>( 71 now.time_since_epoch()) % 72 1000; 73 auto now_time_t = std::chrono::system_clock::to_time_t(now); 74 ss << std::put_time(std::localtime(&now_time_t), "%Y-%m-%d %H:%M:%S"); 75 ss << '.' << std::setfill('0') << std::setw(3) << millis.count(); 76 std::string start_timestamp = ss.str(); 77 LOG_INFO( 78 "%s: %s: took %zu us", 79 start_timestamp.c_str(), 80 stopwatch_logs[current_buffer_index].message.c_str(), 81 static_cast<size_t>(std::chrono::duration_cast<std::chrono::microseconds>( 82 stopwatch_logs[current_buffer_index].end_timestamp - 83 stopwatch_logs[current_buffer_index].start_timestamp) 84 .count())); 85 current_buffer_index++; 86 } 87 LOG_INFO("====================================="); 88 } 89 90 StopWatch::StopWatch(std::string text) 91 : text_(std::move(text)), 92 timestamp_(std::chrono::system_clock::now()), 93 start_timestamp_(std::chrono::high_resolution_clock::now()) {} 94 95 StopWatch::~StopWatch() { 96 StopWatchLog sw_log; 97 sw_log.timestamp = timestamp_; 98 sw_log.start_timestamp = start_timestamp_; 99 sw_log.end_timestamp = std::chrono::high_resolution_clock::now(); 100 sw_log.message = std::move(text_); 101 102 RecordLog(std::move(sw_log)); 103 } 104 105 } // namespace common 106 } // namespace bluetooth 107