RecordReadThread.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. /*
  2. * Copyright (C) 2018 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #pragma once
  17. #include <sys/types.h>
  18. #include <atomic>
  19. #include <condition_variable>
  20. #include <functional>
  21. #include <memory>
  22. #include <mutex>
  23. #include <thread>
  24. #include <android-base/macros.h>
  25. #include <android-base/unique_fd.h>
  26. #include "event_fd.h"
  27. #include "record.h"
  28. namespace simpleperf {
  29. // RecordBuffer is a circular buffer used to cache records in user-space. It allows one read
  30. // thread and one write thread. The record read thread writes records to the buffer, and the main
  31. // thread reads records from the buffer.
  32. class RecordBuffer {
  33. public:
  34. RecordBuffer(size_t buffer_size);
  35. size_t size() const { return buffer_size_; }
  36. // Return the size of writable space in the buffer.
  37. size_t GetFreeSize() const;
  38. // Allocate a writable space for a record. Return nullptr if there isn't enough space.
  39. char* AllocWriteSpace(size_t record_size);
  40. // Called after writing a record, let the read thread see the record.
  41. void FinishWrite();
  42. // Get data of the current record. Return nullptr if there is no records in the buffer.
  43. char* GetCurrentRecord();
  44. // Called after reading a record, the space of the record will be writable.
  45. void MoveToNextRecord();
  46. private:
  47. std::atomic_size_t read_head_;
  48. std::atomic_size_t write_head_;
  49. size_t cur_write_record_size_ = 0;
  50. size_t cur_read_record_size_ = 0;
  51. const size_t buffer_size_;
  52. std::unique_ptr<char> buffer_;
  53. DISALLOW_COPY_AND_ASSIGN(RecordBuffer);
  54. };
  55. // Parse positions of different fields in record data.
  56. class RecordParser {
  57. public:
  58. RecordParser(const perf_event_attr& attr);
  59. // Return pos of the time field in the record. If not available, return 0.
  60. size_t GetTimePos(const perf_event_header& header) const;
  61. // Return pos of the user stack size field in the sample record. If not available, return 0.
  62. size_t GetStackSizePos(const std::function<void(size_t,size_t,void*)>& read_record_fn) const;
  63. private:
  64. uint64_t sample_type_;
  65. uint64_t sample_regs_count_;
  66. size_t time_pos_in_sample_records_ = 0;
  67. size_t time_rpos_in_non_sample_records_ = 0;
  68. size_t callchain_pos_in_sample_records_ = 0;
  69. };
  70. // Read records from the kernel buffer belong to an event_fd.
  71. class KernelRecordReader {
  72. public:
  73. KernelRecordReader(EventFd* event_fd);
  74. EventFd* GetEventFd() const { return event_fd_; }
  75. // Get available data in the kernel buffer. Return true if there is some data.
  76. bool GetDataFromKernelBuffer();
  77. // Get header of the current record.
  78. const perf_event_header& RecordHeader() { return record_header_; }
  79. // Get time of the current record.
  80. uint64_t RecordTime() { return record_time_; }
  81. // Read data of the current record.
  82. void ReadRecord(size_t pos, size_t size, void* dest);
  83. // Move to the next record, return false if there is no more records.
  84. bool MoveToNextRecord(const RecordParser& parser);
  85. private:
  86. EventFd* event_fd_;
  87. char* buffer_;
  88. size_t buffer_mask_;
  89. size_t data_pos_ = 0;
  90. size_t data_size_ = 0;
  91. size_t init_data_size_ = 0;
  92. perf_event_header record_header_ = {};
  93. uint64_t record_time_ = 0;
  94. };
  95. // To reduce sample lost rate when recording dwarf based call graph, RecordReadThread uses a
  96. // separate high priority (nice -20) thread to read records from kernel buffers to a RecordBuffer.
  97. class RecordReadThread {
  98. public:
  99. RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr, size_t min_mmap_pages,
  100. size_t max_mmap_pages);
  101. ~RecordReadThread();
  102. void SetBufferLevels(size_t record_buffer_low_level, size_t record_buffer_critical_level) {
  103. record_buffer_low_level_ = record_buffer_low_level;
  104. record_buffer_critical_level_ = record_buffer_critical_level;
  105. }
  106. // Below functions are called in the main thread:
  107. // When there are records in the RecordBuffer, data_callback will be called in the main thread.
  108. bool RegisterDataCallback(IOEventLoop& loop, const std::function<bool()>& data_callback);
  109. // Create and read kernel buffers for new event fds.
  110. bool AddEventFds(const std::vector<EventFd*>& event_fds);
  111. // Destroy kernel buffers of existing event fds.
  112. bool RemoveEventFds(const std::vector<EventFd*>& event_fds);
  113. // Move all available records in kernel buffers to the RecordBuffer.
  114. bool SyncKernelBuffer();
  115. // Stop the read thread, no more records will be put into the RecordBuffer.
  116. bool StopReadThread();
  117. // If available, return the next record in the RecordBuffer, otherwise return nullptr.
  118. std::unique_ptr<Record> GetRecord();
  119. void GetLostRecords(size_t* lost_samples, size_t* lost_non_samples, size_t* cut_stack_samples) {
  120. *lost_samples = lost_samples_;
  121. *lost_non_samples = lost_non_samples_;
  122. *cut_stack_samples = cut_stack_samples_;
  123. }
  124. private:
  125. enum Cmd {
  126. NO_CMD,
  127. CMD_ADD_EVENT_FDS,
  128. CMD_REMOVE_EVENT_FDS,
  129. CMD_SYNC_KERNEL_BUFFER,
  130. CMD_STOP_THREAD,
  131. };
  132. bool SendCmdToReadThread(Cmd cmd, void* cmd_arg);
  133. // Below functions are called in the read thread:
  134. void RunReadThread();
  135. void IncreaseThreadPriority();
  136. Cmd GetCmd();
  137. bool HandleCmd(IOEventLoop& loop);
  138. bool HandleAddEventFds(IOEventLoop& loop, const std::vector<EventFd*>& event_fds);
  139. bool HandleRemoveEventFds(const std::vector<EventFd*>& event_fds);
  140. bool ReadRecordsFromKernelBuffer();
  141. void PushRecordToRecordBuffer(KernelRecordReader* kernel_record_reader);
  142. bool SendDataNotificationToMainThread();
  143. RecordBuffer record_buffer_;
  144. // When free size in record buffer is below low level, we cut stack data of sample records to 1K.
  145. size_t record_buffer_low_level_;
  146. // When free size in record buffer is below critical level, we drop sample records to avoid
  147. // losing more important records (like mmap or fork records).
  148. size_t record_buffer_critical_level_;
  149. RecordParser record_parser_;
  150. perf_event_attr attr_;
  151. size_t stack_size_in_sample_record_ = 0;
  152. size_t min_mmap_pages_;
  153. size_t max_mmap_pages_;
  154. // Used to pass command notification from the main thread to the read thread.
  155. android::base::unique_fd write_cmd_fd_;
  156. android::base::unique_fd read_cmd_fd_;
  157. std::mutex cmd_mutex_;
  158. std::condition_variable cmd_finish_cond_;
  159. Cmd cmd_;
  160. void* cmd_arg_;
  161. bool cmd_result_;
  162. // Used to send data notification from the read thread to the main thread.
  163. android::base::unique_fd write_data_fd_;
  164. android::base::unique_fd read_data_fd_;
  165. std::atomic_bool has_data_notification_;
  166. std::unique_ptr<std::thread> read_thread_;
  167. std::vector<KernelRecordReader> kernel_record_readers_;
  168. size_t lost_samples_ = 0;
  169. size_t lost_non_samples_ = 0;
  170. size_t cut_stack_samples_ = 0;
  171. };
  172. } // namespace simpleperf