[sampling heap profiler] Speed up RecordFree by removing atomic locks.

The patch removes all the atomic-based locking from RecordFree function.
To make it work we prohibit rehashing the samples map. Instead if the
map comes close enough to the rehashing treshold, the map gets copied
into a larger one which becomes current for all future accesses from
the RecordFree function. To resolve the race with threads that might
currently run the RecordFree we keep all the previous copies of the map.

Performance wise it speeds up the sampler 2x on sampling interval of 128KB.
It comes at the cost of spending twice more memory for samples map.

BUG=803276

Change-Id: Icdcdfb7b168b10d9d83d1277328ccc7944d0d795
Reviewed-on: https://chromium-review.googlesource.com/1060088
Reviewed-by: Dmitry Gozman <[email protected]>
Reviewed-by: Primiano Tucci <[email protected]>
Commit-Queue: Alexei Filippov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#561159}
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.h b/base/sampling_heap_profiler/sampling_heap_profiler.h
index 3f2f227a..c579220 100644
--- a/base/sampling_heap_profiler/sampling_heap_profiler.h
+++ b/base/sampling_heap_profiler/sampling_heap_profiler.h
@@ -2,9 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H
-#define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H
+#ifndef BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
+#define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_
 
+#include <memory>
+#include <stack>
 #include <unordered_map>
 #include <vector>
 
@@ -79,6 +81,8 @@
   static SamplingHeapProfiler* GetInstance();
 
  private:
+  using SamplesMap = std::unordered_map<void*, Sample>;
+
   SamplingHeapProfiler();
   ~SamplingHeapProfiler() = delete;
 
@@ -92,12 +96,14 @@
                      uint32_t skip_frames);
   void DoRecordFree(void* address);
   void RecordStackTrace(Sample*, uint32_t skip_frames);
-  bool MayRehashOnInsert();
+  SamplesMap& EnsureNoRehashingMap();
+  static SamplesMap& samples();
 
   base::ThreadLocalBoolean entered_;
   base::Lock mutex_;
-  std::unordered_map<void*, Sample> samples_;
+  std::stack<std::unique_ptr<SamplesMap>> sample_maps_;
   std::vector<SamplesObserver*> observers_;
+  uint32_t last_sample_ordinal_ = 0;
 
   static SamplingHeapProfiler* instance_;
 
@@ -108,4 +114,4 @@
 
 }  // namespace base
 
-#endif  // BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H
+#endif  // BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_