diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp index 04fd59d95..625cbdec4 100644 --- a/logd/LogStatistics.cpp +++ b/logd/LogStatistics.cpp @@ -308,8 +308,9 @@ template void LogStatistics::WorstTwoWithThreshold(const LogHashtable& table, size_t threshold, int* worst, size_t* worst_sizes, size_t* second_worst_sizes) const { + std::array max_keys; std::array max_entries; - table.MaxEntries(AID_ROOT, 0, &max_entries); + table.MaxEntries(AID_ROOT, 0, max_keys, max_entries); if (max_entries[0] == nullptr || max_entries[1] == nullptr) { return; } @@ -317,7 +318,7 @@ void LogStatistics::WorstTwoWithThreshold(const LogHashtable& tabl // b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is // 100 characters. if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->dropped_count())) { - *worst = max_entries[0]->key(); + *worst = *max_keys[0]; *second_worst_sizes = max_entries[1]->getSizes(); if (*second_worst_sizes < threshold) { *second_worst_sizes = threshold; @@ -340,13 +341,14 @@ void LogStatistics::WorstTwoTags(size_t threshold, int* worst, size_t* worst_siz void LogStatistics::WorstTwoSystemPids(log_id id, size_t worst_uid_sizes, int* worst, size_t* second_worst_sizes) const { auto lock = std::lock_guard{lock_}; + std::array max_keys; std::array max_entries; - pidSystemTable[id].MaxEntries(AID_SYSTEM, 0, &max_entries); + pidSystemTable[id].MaxEntries(AID_SYSTEM, 0, max_keys, max_entries); if (max_entries[0] == nullptr || max_entries[1] == nullptr) { return; } - *worst = max_entries[0]->key(); + *worst = *max_keys[0]; *second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes(); } @@ -412,11 +414,12 @@ void LogStatistics::FormatTmp(const char* nameTmp, uid_t uid, std::string& name, } } -std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUIRES(stat.lock_) { - std::string name = android::base::StringPrintf("%u", uid_); +std::string UidEntry::format(const LogStatistics& stat, log_id_t id, uid_t uid) const + REQUIRES(stat.lock_) { + std::string name = android::base::StringPrintf("%u", uid); std::string size = android::base::StringPrintf("%zu", getSizes()); - stat.FormatTmp(nullptr, uid_, name, size, 6); + stat.FormatTmp(nullptr, uid, name, size, 6); std::string pruned = ""; if (worstUidEnabledForLogid(id)) { @@ -474,19 +477,20 @@ std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUI std::string output = formatLine(name, size, pruned); - if (uid_ != AID_SYSTEM) { + if (uid != AID_SYSTEM) { return output; } static const size_t maximum_sorted_entries = 32; - std::array sorted; - stat.pidSystemTable[id].MaxEntries(uid_, 0, &sorted); + std::array sorted_pids; + std::array sorted_entries; + stat.pidSystemTable[id].MaxEntries(uid, 0, sorted_pids, sorted_entries); std::string byPid; size_t index; bool hasDropped = false; for (index = 0; index < maximum_sorted_entries; ++index) { - const PidEntry* entry = sorted[index]; + const PidEntry* entry = sorted_entries[index]; if (!entry) { break; } @@ -496,7 +500,7 @@ std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUI if (entry->dropped_count()) { hasDropped = true; } - byPid += entry->format(stat, id); + byPid += entry->format(stat, id, *sorted_pids[index]); } if (index > 1) { // print this only if interesting std::string ditto("\" "); @@ -515,9 +519,9 @@ std::string PidEntry::formatHeader(const std::string& name, std::string("BYTES"), std::string("NUM")); } -std::string PidEntry::format(const LogStatistics& stat, log_id_t /* id */) const +std::string PidEntry::format(const LogStatistics& stat, log_id_t, pid_t pid) const REQUIRES(stat.lock_) { - std::string name = android::base::StringPrintf("%5u/%u", pid_, uid_); + std::string name = android::base::StringPrintf("%5u/%u", pid, uid_); std::string size = android::base::StringPrintf("%zu", getSizes()); stat.FormatTmp(name_, uid_, name, size, 12); @@ -538,9 +542,9 @@ std::string TidEntry::formatHeader(const std::string& name, std::string("NUM")); } -std::string TidEntry::format(const LogStatistics& stat, log_id_t /* id */) const +std::string TidEntry::format(const LogStatistics& stat, log_id_t, pid_t tid) const REQUIRES(stat.lock_) { - std::string name = android::base::StringPrintf("%5u/%u", tid(), uid_); + std::string name = android::base::StringPrintf("%5u/%u", tid, uid_); std::string size = android::base::StringPrintf("%zu", getSizes()); stat.FormatTmp(name_, uid_, name, size, 12); @@ -562,8 +566,7 @@ std::string TagEntry::formatHeader(const std::string& name, log_id_t id) const { std::string("BYTES"), std::string(isprune ? "NUM" : "")); } -std::string TagEntry::format(const LogStatistics& /* stat */, - log_id_t /* id */) const { +std::string TagEntry::format(const LogStatistics&, log_id_t, uint32_t) const { std::string name; if (uid_ == (uid_t)-1) { name = android::base::StringPrintf("%7u", key()); @@ -594,8 +597,7 @@ std::string TagNameEntry::formatHeader(const std::string& name, std::string("BYTES"), std::string("")); } -std::string TagNameEntry::format(const LogStatistics& /* stat */, - log_id_t /* id */) const { +std::string TagNameEntry::format(const LogStatistics&, log_id_t, const TagNameKey& key_name) const { std::string name; std::string pidstr; if (pid_ != (pid_t)-1) { @@ -616,7 +618,7 @@ std::string TagNameEntry::format(const LogStatistics& /* stat */, std::string size = android::base::StringPrintf("%zu", getSizes()); - const char* nameTmp = this->name(); + const char* nameTmp = key_name.data(); if (nameTmp) { size_t lenSpace = std::max(16 - name.length(), (size_t)1); size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() - @@ -684,15 +686,16 @@ std::string LogStatistics::FormatTable(const LogHashtable& table, REQUIRES(lock_) { static const size_t maximum_sorted_entries = 32; std::string output; - std::array sorted; - table.MaxEntries(uid, pid, &sorted); + std::array sorted_keys; + std::array sorted_entries; + table.MaxEntries(uid, pid, sorted_keys, sorted_entries); bool header_printed = false; for (size_t index = 0; index < maximum_sorted_entries; ++index) { - const TEntry* entry = sorted[index]; + const TEntry* entry = sorted_entries[index]; if (!entry) { break; } - if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) { + if (entry->getSizes() <= (sorted_entries[0]->getSizes() / 100)) { break; } if (!header_printed) { @@ -700,7 +703,7 @@ std::string LogStatistics::FormatTable(const LogHashtable& table, output += entry->formatHeader(name, id); header_printed = true; } - output += entry->format(*this, id); + output += entry->format(*this, id, *sorted_keys[index]); } return output; } diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h index 33a4d63f7..9f085dca3 100644 --- a/logd/LogStatistics.h +++ b/logd/LogStatistics.h @@ -44,6 +44,8 @@ for (log_id_t i = LOG_ID_MIN; (i) < LOG_ID_MAX; (i) = (log_id_t)((i) + 1)) class LogStatistics; +class UidEntry; +class PidEntry; struct LogStatisticsElement { uid_t uid; @@ -95,31 +97,43 @@ class LogHashtable { // Returns a sorted array of up to len highest entries sorted by size. If fewer than len // entries are found, their positions are set to nullptr. template - void MaxEntries(uid_t uid, pid_t pid, std::array* out) const { - auto& retval = *out; - retval.fill(nullptr); - for (const_iterator it = map.begin(); it != map.end(); ++it) { - const TEntry& entry = it->second; - - if (uid != AID_ROOT && uid != entry.uid()) { + void MaxEntries(uid_t uid, pid_t pid, std::array& out_keys, + std::array& out_entries) const { + out_keys.fill(nullptr); + out_entries.fill(nullptr); + for (const auto& [key, entry] : map) { + uid_t entry_uid = 0; + if constexpr (std::is_same_v) { + entry_uid = key; + } else { + entry_uid = entry.uid(); + } + if (uid != AID_ROOT && uid != entry_uid) { continue; } - if (pid && entry.pid() && pid != entry.pid()) { + pid_t entry_pid = 0; + if constexpr (std::is_same_v) { + entry_pid = key; + } else { + entry_pid = entry.pid(); + } + if (pid && entry_pid && pid != entry_pid) { continue; } size_t sizes = entry.getSizes(); ssize_t index = len - 1; - while ((!retval[index] || (sizes > retval[index]->getSizes())) && - (--index >= 0)) + while ((!out_entries[index] || sizes > out_entries[index]->getSizes()) && --index >= 0) ; if (++index < (ssize_t)len) { size_t num = len - index - 1; if (num) { - memmove(&retval[index + 1], &retval[index], - num * sizeof(retval[0])); + memmove(&out_keys[index + 1], &out_keys[index], num * sizeof(out_keys[0])); + memmove(&out_entries[index + 1], &out_entries[index], + num * sizeof(out_entries[0])); } - retval[index] = &entry; + out_keys[index] = &key; + out_entries[index] = &entry; } } } @@ -229,10 +243,8 @@ class EntryBaseDropped : public EntryBase { class UidEntry : public EntryBaseDropped { public: explicit UidEntry(const LogStatisticsElement& element) - : EntryBaseDropped(element), uid_(element.uid), pid_(element.pid) {} + : EntryBaseDropped(element), pid_(element.pid) {} - uid_t key() const { return uid_; } - uid_t uid() const { return key(); } pid_t pid() const { return pid_; } void Add(const LogStatisticsElement& element) { @@ -243,10 +255,9 @@ class UidEntry : public EntryBaseDropped { } std::string formatHeader(const std::string& name, log_id_t id) const; - std::string format(const LogStatistics& stat, log_id_t id) const; + std::string format(const LogStatistics& stat, log_id_t id, uid_t uid) const; private: - const uid_t uid_; pid_t pid_; }; @@ -258,23 +269,16 @@ class PidEntry : public EntryBaseDropped { public: explicit PidEntry(pid_t pid) : EntryBaseDropped(), - pid_(pid), uid_(android::pidToUid(pid)), name_(android::pidToName(pid)) {} explicit PidEntry(const LogStatisticsElement& element) - : EntryBaseDropped(element), - pid_(element.pid), - uid_(element.uid), - name_(android::pidToName(pid_)) {} + : EntryBaseDropped(element), uid_(element.uid), name_(android::pidToName(element.pid)) {} PidEntry(const PidEntry& element) : EntryBaseDropped(element), - pid_(element.pid_), uid_(element.uid_), name_(element.name_ ? strdup(element.name_) : nullptr) {} ~PidEntry() { free(name_); } - pid_t key() const { return pid_; } - pid_t pid() const { return key(); } uid_t uid() const { return uid_; } const char* name() const { return name_; } @@ -301,10 +305,9 @@ class PidEntry : public EntryBaseDropped { } std::string formatHeader(const std::string& name, log_id_t id) const; - std::string format(const LogStatistics& stat, log_id_t id) const; + std::string format(const LogStatistics& stat, log_id_t id, pid_t pid) const; private: - const pid_t pid_; uid_t uid_; char* name_; }; @@ -313,26 +316,21 @@ class TidEntry : public EntryBaseDropped { public: TidEntry(pid_t tid, pid_t pid) : EntryBaseDropped(), - tid_(tid), pid_(pid), uid_(android::pidToUid(tid)), name_(android::tidToName(tid)) {} explicit TidEntry(const LogStatisticsElement& element) : EntryBaseDropped(element), - tid_(element.tid), pid_(element.pid), uid_(element.uid), - name_(android::tidToName(tid_)) {} + name_(android::tidToName(element.tid)) {} TidEntry(const TidEntry& element) : EntryBaseDropped(element), - tid_(element.tid_), pid_(element.pid_), uid_(element.uid_), name_(element.name_ ? strdup(element.name_) : nullptr) {} ~TidEntry() { free(name_); } - pid_t key() const { return tid_; } - pid_t tid() const { return key(); } pid_t pid() const { return pid_; } uid_t uid() const { return uid_; } const char* name() const { return name_; } @@ -362,10 +360,9 @@ class TidEntry : public EntryBaseDropped { } std::string formatHeader(const std::string& name, log_id_t id) const; - std::string format(const LogStatistics& stat, log_id_t id) const; + std::string format(const LogStatistics& stat, log_id_t id, pid_t pid) const; private: - const pid_t tid_; pid_t pid_; uid_t uid_; char* name_; @@ -392,7 +389,7 @@ class TagEntry : public EntryBaseDropped { } std::string formatHeader(const std::string& name, log_id_t id) const; - std::string format(const LogStatistics& stat, log_id_t id) const; + std::string format(const LogStatistics& stat, log_id_t id, uint32_t) const; private: const uint32_t tag_; @@ -490,18 +487,11 @@ struct std::hash class TagNameEntry : public EntryBase { public: explicit TagNameEntry(const LogStatisticsElement& element) - : EntryBase(element), - tid_(element.tid), - pid_(element.pid), - uid_(element.uid), - name_(element) {} + : EntryBase(element), tid_(element.tid), pid_(element.pid), uid_(element.uid) {} - const TagNameKey& key() const { return name_; } pid_t tid() const { return tid_; } pid_t pid() const { return pid_; } uid_t uid() const { return uid_; } - const char* name() const { return name_.data(); } - size_t getNameAllocLength() const { return name_.getAllocLength(); } void Add(const LogStatisticsElement& element) { if (uid_ != element.uid) { @@ -517,13 +507,12 @@ class TagNameEntry : public EntryBase { } std::string formatHeader(const std::string& name, log_id_t id) const; - std::string format(const LogStatistics& stat, log_id_t id) const; + std::string format(const LogStatistics& stat, log_id_t id, const TagNameKey& key_name) const; private: pid_t tid_; pid_t pid_; uid_t uid_; - TagNameKey name_; }; // Log Statistics @@ -584,7 +573,7 @@ class LogStatistics { const char* name = it.second.name(); if (name) size += strlen(name) + 1; } - for (auto it : tagNameTable) size += it.second.getNameAllocLength(); + for (auto it : tagNameTable) size += it.first.getAllocLength(); log_id_for_each(id) { size += uidTable[id].sizeOf(); size += uidTable[id].size() * sizeof(uidTable_t::iterator);