| 188 | } |
| 189 | |
| 190 | void ContentionProfiler::flush_to_disk(bool ending) { |
| 191 | BT_VLOG << "flush_to_disk(ending=" << ending << ")"; |
| 192 | |
| 193 | // Serialize contentions in _dedup_map into _disk_buf. |
| 194 | if (!_dedup_map.empty()) { |
| 195 | BT_VLOG << "dedup_map=" << _dedup_map.size(); |
| 196 | butil::IOBufBuilder os; |
| 197 | for (ContentionMap::const_iterator |
| 198 | it = _dedup_map.begin(); it != _dedup_map.end(); ++it) { |
| 199 | SampledContention* c = it->second; |
| 200 | os << c->duration_ns << ' ' << (size_t)ceil(c->count) << " @"; |
| 201 | for (int i = SKIPPED_STACK_FRAMES; i < c->nframes; ++i) { |
| 202 | os << ' ' << (void*)c->stack[i]; |
| 203 | } |
| 204 | os << '\n'; |
| 205 | c->destroy(); |
| 206 | } |
| 207 | _dedup_map.clear(); |
| 208 | _disk_buf.append(os.buf()); |
| 209 | } |
| 210 | |
| 211 | // Append /proc/self/maps to the end of the contention file, required by |
| 212 | // pprof.pl, otherwise the functions in sys libs are not interpreted. |
| 213 | if (ending) { |
| 214 | BT_VLOG << "Append /proc/self/maps"; |
| 215 | // Failures are not critical, don't return directly. |
| 216 | butil::IOPortal mem_maps; |
| 217 | const butil::fd_guard fd(open("/proc/self/maps", O_RDONLY)); |
| 218 | if (fd >= 0) { |
| 219 | while (true) { |
| 220 | ssize_t nr = mem_maps.append_from_file_descriptor(fd, 8192); |
| 221 | if (nr < 0) { |
| 222 | if (errno == EINTR) { |
| 223 | continue; |
| 224 | } |
| 225 | PLOG(ERROR) << "Fail to read /proc/self/maps"; |
| 226 | break; |
| 227 | } |
| 228 | if (nr == 0) { |
| 229 | _disk_buf.append(mem_maps); |
| 230 | break; |
| 231 | } |
| 232 | } |
| 233 | } else { |
| 234 | PLOG(ERROR) << "Fail to open /proc/self/maps"; |
| 235 | } |
| 236 | } |
| 237 | // Write _disk_buf into _filename |
| 238 | butil::File::Error error; |
| 239 | butil::FilePath path(_filename); |
| 240 | butil::FilePath dir = path.DirName(); |
| 241 | if (!butil::CreateDirectoryAndGetError(dir, &error)) { |
| 242 | LOG(ERROR) << "Fail to create directory=`" << dir.value() |
| 243 | << "', " << error; |
| 244 | return; |
| 245 | } |
| 246 | // Truncate on first write, append on later writes. |
| 247 | int flag = O_APPEND; |
nothing calls this directly
no test coverage detected