summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/abseil-cpp/absl/profiling/internal/profile_builder.h
blob: e4f29097d9f4fe36f4e94753549e29f54cd54433 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2025 The Abseil Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may
// obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_
#define ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_

#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {

// Field numbers for perftools.profiles.Profile.
// https://github.com/google/pprof/blob/master/proto/profile.proto
struct ProfileProto {
  static constexpr int kSampleType = 1;
  static constexpr int kSample = 2;
  static constexpr int kMapping = 3;
  static constexpr int kLocation = 4;
  static constexpr int kStringTable = 6;
  static constexpr int kDropFrames = 7;
  static constexpr int kComment = 13;
  static constexpr int kDefaultSampleType = 14;
};

struct ValueTypeProto {
  static constexpr int kType = 1;
  static constexpr int kUnit = 2;
};

struct SampleProto {
  static constexpr int kLocationId = 1;
  static constexpr int kValue = 2;
  static constexpr int kLabel = 3;
};

struct LabelProto {
  static constexpr int kKey = 1;
  static constexpr int kStr = 2;
  static constexpr int kNum = 3;
  static constexpr int kNumUnit = 4;
};

struct MappingProto {
  static constexpr int kId = 1;
  static constexpr int kMemoryStart = 2;
  static constexpr int kMemoryLimit = 3;
  static constexpr int kFileOffset = 4;
  static constexpr int kFilename = 5;
  static constexpr int kBuildId = 6;
};

struct LocationProto {
  static constexpr int kId = 1;
  static constexpr int kMappingId = 2;
  static constexpr int kAddress = 3;
};

enum class StringId : size_t {};
enum class LocationId : size_t {};
enum class MappingId : size_t {};

// A helper class to build a profile protocol buffer.
class ProfileBuilder {
 public:
  struct Mapping {
    uint64_t start;
    uint64_t limit;
    uint64_t offset;
    std::string filename;
    std::string build_id;
  };

  StringId InternString(absl::string_view str);

  LocationId InternLocation(const void* address);

  void AddSample(int64_t value, absl::Span<const void* const> stack,
                 absl::Span<const std::pair<StringId, int64_t>> labels);

  void AddSampleType(StringId type, StringId unit);

  // Adds the current process mappings to the profile.
  void AddCurrentMappings();

  // Adds a single mapping to the profile and to lookup cache and returns the
  // resulting ID.
  MappingId AddMapping(uintptr_t memory_start, uintptr_t memory_limit,
                       uintptr_t file_offset, absl::string_view filename,
                       absl::string_view build_id);

  std::string Emit() &&;

  void set_drop_frames_id(StringId drop_frames_id);
  void set_comment_id(StringId comment_id);
  void set_default_sample_type_id(StringId default_sample_type_id);

 private:
  // We turn off hashtable profiling for the ProfileBuilder's own tables.
  //
  // This is necessary since we use this class to construct hashtable profiles,
  // which entails walking the hashtable profiling data and we don't want to
  // encounter it reentrantly.
  template <typename T>
  struct HashtablezBarrier : std::allocator<T> {
    HashtablezBarrier() = default;

    template <typename U>
    HashtablezBarrier(const HashtablezBarrier<U>&) {}

    template <class U>
    struct rebind {
      using other = HashtablezBarrier<U>;
    };
  };

  template <typename K, typename V>
  using UnprofiledHashMap = absl::flat_hash_map<
      K, V, DefaultHashContainerHash<K>, DefaultHashContainerEq<K>,
      HashtablezBarrier<std::pair<const K, V>>>;

  UnprofiledHashMap<std::string, StringId> string_table_{{"", StringId(0)}};
  UnprofiledHashMap<uintptr_t, LocationId> location_table_;
  // mapping_table_ stores the start address of each mapping in mapping_
  // to its index.
  absl::btree_map<uintptr_t, size_t> mapping_table_;
  std::vector<Mapping> mappings_;

  std::vector<std::string> sample_types_;
  std::vector<std::string> samples_;

  StringId drop_frames_id_{};
  StringId comment_id_{};
  StringId default_sample_type_id_{};
};

}  // namespace debugging_internal
ABSL_NAMESPACE_END
}  // namespace absl

#endif  // ABSL_PROFILING_INTERNAL_PROFILE_BUILDER_H_