1616
1717#include " velox/common/process/TraceContext.h"
1818
19+ #include " velox/common/process/ThreadLocalRegistry.h"
20+
1921#include < sstream>
2022
2123namespace facebook ::velox::process {
2224
2325namespace {
24- folly::Synchronized<std::unordered_map<std::string, TraceData>>& traceMap () {
25- static folly::Synchronized<std::unordered_map<std::string, TraceData>>
26- staticTraceMap;
27- return staticTraceMap;
28- }
26+
27+ // We use thread local instead lock here since the critical path is on write
28+ // side.
29+ using Registry = ThreadLocalRegistry<folly::F14FastMap<std::string, TraceData>>;
30+ auto registry = std::make_shared<Registry>();
31+ thread_local Registry::Reference threadLocalTraceData (registry);
32+
2933} // namespace
3034
3135TraceContext::TraceContext (std::string label, bool isTemporary)
3236 : label_(std::move(label)),
3337 enterTime_ (std::chrono::steady_clock::now()),
3438 isTemporary_(isTemporary) {
35- traceMap (). withWLock ([&](auto & counts) {
39+ threadLocalTraceData. withValue ([&](auto & counts) {
3640 auto & data = counts[label_];
3741 ++data.numThreads ;
3842 if (data.numThreads == 1 ) {
@@ -43,45 +47,59 @@ TraceContext::TraceContext(std::string label, bool isTemporary)
4347}
4448
4549TraceContext::~TraceContext () {
46- traceMap ().withWLock ([&](auto & counts) {
47- auto & data = counts[label_];
48- --data.numThreads ;
50+ threadLocalTraceData.withValue ([&](auto & counts) {
51+ auto it = counts.find (label_);
52+ auto & data = it->second ;
53+ if (--data.numThreads == 0 && isTemporary_) {
54+ counts.erase (it);
55+ return ;
56+ }
4957 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
5058 std::chrono::steady_clock::now () - enterTime_)
5159 .count ();
5260 data.totalMs += ms;
5361 data.maxMs = std::max<uint64_t >(data.maxMs , ms);
54- if (!data.numThreads && isTemporary_) {
55- counts.erase (label_);
56- }
5762 });
5863}
5964
6065// static
6166std::string TraceContext::statusLine () {
6267 std::stringstream out;
6368 auto now = std::chrono::steady_clock::now ();
64- traceMap (). withRLock ([&]( auto & counts) {
65- for (auto & pair : counts) {
66- if (pair.second .numThreads ) {
67- auto continued = std::chrono::duration_cast<std::chrono::milliseconds>(
68- now - pair.second .startTime )
69- .count ();
69+ auto counts = status ();
70+ for (auto & pair : counts) {
71+ if (pair.second .numThreads ) {
72+ auto continued = std::chrono::duration_cast<std::chrono::milliseconds>(
73+ now - pair.second .startTime )
74+ .count ();
7075
71- out << pair.first << " =" << pair.second .numThreads << " entered "
72- << pair.second .numEnters << " avg ms "
73- << (pair.second .totalMs / pair.second .numEnters ) << " max ms "
74- << pair.second .maxMs << " continuous for " << continued
75- << std::endl;
76- }
76+ out << pair.first << " =" << pair.second .numThreads << " entered "
77+ << pair.second .numEnters << " avg ms "
78+ << (pair.second .totalMs / pair.second .numEnters ) << " max ms "
79+ << pair.second .maxMs << " continuous for " << continued << std::endl;
7780 }
78- });
81+ }
7982 return out.str ();
8083}
8184
8285// static
83- std::unordered_map<std::string, TraceData> TraceContext::status () {
84- return traceMap ().withRLock ([&](auto & map) { return map; });
86+ folly::F14FastMap<std::string, TraceData> TraceContext::status () {
87+ folly::F14FastMap<std::string, TraceData> total;
88+ registry->forAllValues ([&](auto & counts) {
89+ for (auto & [k, v] : counts) {
90+ auto & sofar = total[k];
91+ if (sofar.numEnters == 0 ) {
92+ sofar.startTime = v.startTime ;
93+ } else if (v.numEnters > 0 ) {
94+ sofar.startTime = std::min (sofar.startTime , v.startTime );
95+ }
96+ sofar.numThreads += v.numThreads ;
97+ sofar.numEnters += v.numEnters ;
98+ sofar.totalMs += v.totalMs ;
99+ sofar.maxMs = std::max (sofar.maxMs , v.maxMs );
100+ }
101+ });
102+ return total;
85103}
86104
87105} // namespace facebook::velox::process
0 commit comments