Commit 8cf8897e authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by facebook-github-bot-0

Minor optimizations in ExceptionCounterLib

Summary: Avoid allocation and logging inside the throw handler, and some other minor tweaks.

Reviewed By: bort, luciang

Differential Revision: D2921073

fb-gh-sync-id: 4491ab2f85a4251e59ba9394bba5abef0bdf7a10
shipit-source-id: 4491ab2f85a4251e59ba9394bba5abef0bdf7a10
parent d7c3a477
...@@ -19,7 +19,9 @@ ...@@ -19,7 +19,9 @@
#include <iosfwd> #include <iosfwd>
#include <unordered_map> #include <unordered_map>
#include <folly/Range.h>
#include <folly/RWSpinLock.h> #include <folly/RWSpinLock.h>
#include <folly/SpookyHashV2.h>
#include <folly/Synchronized.h> #include <folly/Synchronized.h>
#include <folly/ThreadLocal.h> #include <folly/ThreadLocal.h>
...@@ -31,8 +33,9 @@ using namespace folly::exception_tracer; ...@@ -31,8 +33,9 @@ using namespace folly::exception_tracer;
namespace { namespace {
// We are using hash of the stack trace to uniquely identify the exception // We use the hash of stack trace and exception type to uniquely
using ExceptionId = uintptr_t; // identify the exception.
using ExceptionId = uint64_t;
using ExceptionStatsHolderType = using ExceptionStatsHolderType =
std::unordered_map<ExceptionId, ExceptionStats>; std::unordered_map<ExceptionId, ExceptionStats>;
...@@ -40,19 +43,12 @@ using ExceptionStatsHolderType = ...@@ -40,19 +43,12 @@ using ExceptionStatsHolderType =
struct ExceptionStatsStorage { struct ExceptionStatsStorage {
void appendTo(ExceptionStatsHolderType& data) { void appendTo(ExceptionStatsHolderType& data) {
ExceptionStatsHolderType tempHolder; ExceptionStatsHolderType tempHolder;
SYNCHRONIZED(statsHolder) { statsHolder->swap(tempHolder);
using std::swap;
swap(statsHolder, tempHolder);
}
for (const auto& myData : tempHolder) { for (const auto& myData : tempHolder) {
const auto& myStat = myData.second; auto inserted = data.insert(myData);
if (!inserted.second) {
auto it = data.find(myData.first); inserted.first->second.count += myData.second.count;
if (it != data.end()) {
it->second.count += myStat.count;
} else {
data.insert(myData);
} }
} }
} }
...@@ -77,23 +73,23 @@ std::vector<ExceptionStats> getExceptionStatistics() { ...@@ -77,23 +73,23 @@ std::vector<ExceptionStats> getExceptionStatistics() {
std::vector<ExceptionStats> result; std::vector<ExceptionStats> result;
result.reserve(accumulator.size()); result.reserve(accumulator.size());
for (const auto& item : accumulator) { for (auto& item : accumulator) {
result.push_back(item.second); result.push_back(std::move(item.second));
} }
std::sort(result.begin(), std::sort(result.begin(),
result.end(), result.end(),
[](const ExceptionStats& lhs, const ExceptionStats& rhs) { [](const ExceptionStats& lhs, const ExceptionStats& rhs) {
return (lhs.count > rhs.count); return lhs.count > rhs.count;
}); });
return result; return result;
} }
std::ostream& operator<<(std::ostream& out, const ExceptionStats& stats) { std::ostream& operator<<(std::ostream& out, const ExceptionStats& stats) {
out << "Exception report: " << std::endl; out << "Exception report: \n"
out << "Exception count: " << stats.count << std::endl; << "Exception count: " << stats.count << "\n"
out << stats.info; << stats.info;
return out; return out;
} }
...@@ -108,26 +104,29 @@ namespace { ...@@ -108,26 +104,29 @@ namespace {
* Information is being stored in thread local storage. * Information is being stored in thread local storage.
*/ */
void throwHandler(void*, std::type_info* exType, void (*)(void*)) noexcept { void throwHandler(void*, std::type_info* exType, void (*)(void*)) noexcept {
ExceptionInfo info; // This array contains the exception type and the stack frame
info.type = exType; // pointers so they get all hashed together.
auto& frames = info.frames; uintptr_t frames[kMaxFrames + 1];
frames[0] = reinterpret_cast<uintptr_t>(exType);
frames.resize(kMaxFrames); auto n = folly::symbolizer::getStackTrace(frames + 1, kMaxFrames);
auto n = folly::symbolizer::getStackTrace(frames.data(), kMaxFrames);
if (n == -1) { if (n == -1) {
LOG(ERROR) << "Invalid stack frame"; // If we fail to collect the stack trace for this exception we
return; // just log it under empty stack trace.
n = 0;
} }
frames.resize(n); auto exceptionId =
auto exceptionId = folly::hash::hash_range(frames.begin(), frames.end()); folly::hash::SpookyHashV2::Hash64(frames, (n + 1) * sizeof(frames[0]), 0);
SYNCHRONIZED(holder, gExceptionStats->statsHolder) { SYNCHRONIZED(holder, gExceptionStats->statsHolder) {
auto it = holder.find(exceptionId); auto it = holder.find(exceptionId);
if (it != holder.end()) { if (it != holder.end()) {
++it->second.count; ++it->second.count;
} else { } else {
ExceptionInfo info;
info.type = exType;
info.frames.assign(frames + 1, frames + 1 + n);
holder.emplace(exceptionId, ExceptionStats{1, std::move(info)}); holder.emplace(exceptionId, ExceptionStats{1, std::move(info)});
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment