| 142 | ContentionStacks* g_contention_stacks = nullptr; |
| 143 | |
| 144 | void ContentionStacks::AddStack(const StackTrace& s, int64_t cycles) { |
| 145 | uint64_t hash = s.HashCode(); |
| 146 | |
| 147 | // Linear probe up to 4 attempts before giving up |
| 148 | for (int i = 0; i < kNumLinearProbeAttempts; i++) { |
| 149 | Entry* e = &entries_[(hash + i) % kNumEntries]; |
| 150 | if (!e->lock.TryLock()) { |
| 151 | // If we fail to lock it, we can safely just use a different slot. |
| 152 | // It's OK if a single stack shows up multiple times, because pprof |
| 153 | // aggregates them in the end anyway. |
| 154 | continue; |
| 155 | } |
| 156 | |
| 157 | if (e->trip_count == 0) { |
| 158 | // It's an un-claimed slot. Claim it. |
| 159 | e->hash = hash; |
| 160 | e->trace.CopyFrom(s); |
| 161 | } else if (e->hash != hash || !e->trace.Equals(s)) { |
| 162 | // It's claimed by a different stack trace. |
| 163 | e->lock.Unlock(); |
| 164 | continue; |
| 165 | } |
| 166 | |
| 167 | // Contribute to the stats for this stack. |
| 168 | e->cycle_count += cycles; |
| 169 | e->trip_count++; |
| 170 | e->lock.Unlock(); |
| 171 | return; |
| 172 | } |
| 173 | |
| 174 | // If we failed to find a matching hashtable slot, or we hit lock contention |
| 175 | // trying to record our sample, add it to the dropped sample count. |
| 176 | dropped_samples_.Increment(); |
| 177 | } |
| 178 | |
| 179 | void ContentionStacks::Flush(std::ostringstream* out, int64_t* dropped) { |
| 180 | uint64_t iterator = 0; |