• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_RUNTIME_DPROFILER_TRACE_H_
17 #define PANDA_RUNTIME_DPROFILER_TRACE_H_
18 
19 #include <memory>
20 #include <string>
21 #include <unordered_set>
22 #include "macros.h"
23 #include "include/mem/panda_containers.h"
24 #include "include/mem/panda_string.h"
25 #include "include/mem/panda_smart_pointers.h"
26 #include "include/mem/panda_containers.h"
27 #include "include/runtime.h"
28 #include "include/runtime_notification.h"
29 #include "runtime/include/method.h"
30 #include "runtime/include/language_context.h"
31 #include "os/mutex.h"
32 
33 namespace panda {
34 
35 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
36 static os::memory::Mutex trace_lock;
37 enum EventFlag {
38     TRACE_METHOD_ENTER = 0x00,
39     TRACE_METHOD_EXIT = 0x01,
40     TRACE_METHOD_UNWIND = 0x02,
41 };
42 class Trace : public RuntimeListener {
43 public:
44     static constexpr size_t ENCODE_EVENT_BITS = 2;
WriteDataByte(uint8_t * data,uint64_t value,uint8_t size)45     static void WriteDataByte(uint8_t *data, uint64_t value, uint8_t size)
46     {
47         for (uint8_t i = 0; i < size; i++) {
48             *data = static_cast<uint8_t>(value);
49             value = value >> WRITE_LENGTH;
50             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
51             data++;
52         }
53     }
54 
GetDataFromBuffer(const uint8_t * buffer,size_t num)55     static uint64_t GetDataFromBuffer(const uint8_t *buffer, size_t num)
56     {
57         uint64_t data = 0;
58         for (size_t i = 0; i < num; i++) {
59             // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic, readability-magic-numbers)
60             data |= static_cast<uint64_t>(buffer[i]) << (i * 8U);
61         }
62         return data;
63     }
64 
65     static void StartTracing(const char *trace_filename, size_t buffer_size);
66 
67     static void TriggerTracing();
68 
69     void MethodEntry(ManagedThread *thread, Method *method) override;
70     void MethodExit(ManagedThread *thread, Method *method) override;
71 
72     void SaveTracingData();
73 
74     static void StopTracing();
75 
76     static bool is_tracing;
77 
78     ~Trace() override;
79 
80     uint64_t GetAverageTime();
81 
82 protected:
83     explicit Trace(PandaUniquePtr<panda::os::unix::file::File> trace_file, size_t buffer_size);
84     uint32_t EncodeMethodToId(Method *method);
85     virtual PandaString GetThreadName(ManagedThread *thread) = 0;
86     virtual PandaString GetMethodDetailInfo(Method *method) = 0;
87 
88 private:
89     static constexpr size_t TRACE_HEADER_REAL_LENGTH = 18U;
90 
91     static const char TRACE_STAR_CHAR = '*';
92     static const uint16_t TRACE_HEADER_LENGTH = 32;
93     static const uint32_t MAGIC_VALUE = 0x574f4c53;
94     static const uint16_t TRACE_VERSION = 3;
95     static const uint16_t TRACE_ITEM_SIZE = 14;
96 
97     static const uint32_t FILE_SIZE = 8 * 1024 * 1024;
98 
99     // used to define the number we need to right shift
100     static const uint8_t WRITE_LENGTH = 8;
101 
102     // used to define the number of this item we have writed  just now
103     const uint8_t NUMBER_OF_2BYTES = 2;
104     const uint8_t NUMBER_OF_4BYTES = 4;
105     const uint8_t NUMBER_OF_8BYTES = 8;
106 
107     const int32_t LOOP_NUMBER = 10000;
108     const int32_t DIVIDE_NUMBER = 10;
109 
110     PandaUniquePtr<RuntimeListener> listener_;
111 
112     os::memory::Mutex methods_lock_;
113     // all methods are encoded to id, and put method、id into this map
114     PandaMap<Method *, uint32_t> method_id_pandamap_ GUARDED_BY(methods_lock_);
115     PandaVector<Method *> methods_called_vector_ GUARDED_BY(methods_lock_);
116 
117     os::memory::Mutex thread_info_lock_;
118     PandaSet<PandaString> thread_info_set_ GUARDED_BY(thread_info_lock_);
119 
120     uint32_t EncodeMethodAndEventToId(Method *method, EventFlag flag);
121     Method *DecodeIdToMethod(uint32_t id);
122 
123     void GetCalledMethods(size_t end_offset, PandaSet<Method *> *called_methods);
124 
125     void GetTimes(uint32_t *thread_time, uint32_t *real_time);
126 
127     void WriteInfoToBuf(const ManagedThread *thread, Method *method, EventFlag event, uint32_t thread_time,
128                         uint32_t real_time);
129 
130     void RecordThreadsInfo(PandaOStringStream *os);
131     void RecordMethodsInfo(PandaOStringStream *os, const PandaSet<Method *> &called_methods);
132 
133     void GetUniqueMethods(size_t buffer_length, PandaSet<Method *> *called_methods_set);
134 
135     static Trace *volatile singleton_trace GUARDED_BY(trace_lock);
136 
137     PandaUniquePtr<panda::os::unix::file::File> trace_file_;
138     const size_t BUFFER_SIZE;
139 
140     PandaUniquePtr<uint8_t[]> buffer_;  // NOLINT(modernize-avoid-c-arrays)
141 
142     const uint64_t TRACE_START_TIME;
143 
144     const uint64_t BASE_CPU_TIME;
145 
146     std::atomic<int32_t> buffer_offset_;
147 
148     bool overbrim_;
149 
150     static LanguageContext ctx;
151 
152     NO_COPY_SEMANTIC(Trace);
153     NO_MOVE_SEMANTIC(Trace);
154 };
155 
156 }  // namespace panda
157 
158 #endif  // PANDA_RUNTIME_DPROFILER_TRACE_H_
159