@@ -227,29 +227,42 @@ BasicQuantileStatMap<ClockT>::registerQuantileStat(
227227 return p->stat ;
228228 }
229229 }
230- auto countersWLock = counters_.wlock ();
231- if (auto * p = folly::get_ptr (countersWLock->bases , name)) {
232- return p->stat ;
233- }
230+
231+ // Construct all the map entries before acquiring the wlock. This could be
232+ // done under an upgrade lock, but we instead prioritize avoiding contention
233+ // on unrelated writes than avoiding wasted work. This is consistent with
234+ // ServiceData::getQuantileStat() which also favors optimistic concurrency
235+ // when calling this method.
236+ auto slidingWindowLengths = stat->getSlidingWindowLengths ();
237+ std::vector<std::pair<std::string, CounterMapEntry>> counterMapEntries;
238+ counterMapEntries.reserve (
239+ statDefs.size () * (1 + slidingWindowLengths.size ()));
234240 for (const auto & statDef : statDefs) {
235241 CounterMapEntry entry;
236242 entry.stat = stat;
237243 entry.statDef = statDef;
238- detail::cachedAddString (
239- *countersWLock, makeKey (name, statDef, folly::none), entry);
240-
241- auto slidingWindowLengths = stat->getSlidingWindowLengths ();
244+ counterMapEntries.emplace_back (makeKey (name, statDef, folly::none), entry);
242245
243246 for (auto slidingWindowLength : slidingWindowLengths) {
244247 entry.slidingWindowLength = slidingWindowLength;
245- detail::cachedAddString (
246- *countersWLock, makeKey (name, statDef, slidingWindowLength), entry);
248+ counterMapEntries. emplace_back (
249+ makeKey (name, statDef, slidingWindowLength), entry);
247250 }
248251 }
252+
253+ auto nameStr = name.str ();
249254 StatMapEntry statMapEntry;
250255 statMapEntry.stat = stat;
251256 statMapEntry.statDefs = std::move (statDefs);
252- countersWLock->bases .emplace (std::move (name), std::move (statMapEntry));
257+
258+ auto countersWLock = counters_.wlock ();
259+ if (auto * p = folly::get_ptr (countersWLock->bases , name)) {
260+ return p->stat ;
261+ }
262+ for (auto && [key, entry] : counterMapEntries) {
263+ detail::cachedAddString (*countersWLock, std::move (key), std::move (entry));
264+ }
265+ countersWLock->bases .emplace (std::move (nameStr), std::move (statMapEntry));
253266 return stat;
254267}
255268
0 commit comments