summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2019-08-08 18:04:17 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-08-08 18:04:17 -0700
commit77605b5b77f55fd870a243d790de52564c0d6ae6 (patch)
treefe09a575f762725be53116b97c933f564caf15c3
parent746d8d3b95ec38e47f37c0a5d41b47e329211488 (diff)
parentf36aa2b28a503e6ba57367d52b8cbda2de2d06af (diff)
downloadextras-77605b5b77f55fd870a243d790de52564c0d6ae6.tar.gz
Merge "simpleperf: add --aux-buffer-size in record cmd."
am: f36aa2b28a Change-Id: Ifac3113a2ba15fa0cb45d9afc8eaa88851286c99
-rw-r--r--simpleperf/RecordReadThread.cpp15
-rw-r--r--simpleperf/RecordReadThread.h4
-rw-r--r--simpleperf/RecordReadThread_test.cpp16
-rw-r--r--simpleperf/cmd_record.cpp25
-rw-r--r--simpleperf/cmd_record_test.cpp12
-rw-r--r--simpleperf/event_selection_set.cpp9
-rw-r--r--simpleperf/event_selection_set.h4
7 files changed, 62 insertions, 23 deletions
diff --git a/simpleperf/RecordReadThread.cpp b/simpleperf/RecordReadThread.cpp
index e2a6d417..b89066b9 100644
--- a/simpleperf/RecordReadThread.cpp
+++ b/simpleperf/RecordReadThread.cpp
@@ -32,9 +32,6 @@ namespace simpleperf {
static constexpr size_t kDefaultLowBufferLevel = 10 * 1024 * 1024u;
static constexpr size_t kDefaultCriticalBufferLevel = 5 * 1024 * 1024u;
-// TODO: add an option to config it.
-static constexpr size_t kDefaultAuxBufferSize = 4 * 1024 * 1024;
-
RecordBuffer::RecordBuffer(size_t buffer_size)
: read_head_(0), write_head_(0), buffer_size_(buffer_size), buffer_(new char[buffer_size]) {
}
@@ -210,9 +207,13 @@ bool KernelRecordReader::MoveToNextRecord(const RecordParser& parser) {
RecordReadThread::RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr,
size_t min_mmap_pages, size_t max_mmap_pages,
- bool allow_cutting_samples)
- : record_buffer_(record_buffer_size), record_parser_(attr), attr_(attr),
- min_mmap_pages_(min_mmap_pages), max_mmap_pages_(max_mmap_pages) {
+ size_t aux_buffer_size, bool allow_cutting_samples)
+ : record_buffer_(record_buffer_size),
+ record_parser_(attr),
+ attr_(attr),
+ min_mmap_pages_(min_mmap_pages),
+ max_mmap_pages_(max_mmap_pages),
+ aux_buffer_size_(aux_buffer_size) {
if (attr.sample_type & PERF_SAMPLE_STACK_USER) {
stack_size_in_sample_record_ = attr.sample_stack_user;
}
@@ -375,7 +376,7 @@ bool RecordReadThread::HandleAddEventFds(IOEventLoop& loop,
break;
}
if (IsEtmEventType(fd->attr().type)) {
- if (!fd->CreateAuxBuffer(kDefaultAuxBufferSize, report_error)) {
+ if (!fd->CreateAuxBuffer(aux_buffer_size_, report_error)) {
fd->DestroyMappedBuffer();
success = false;
break;
diff --git a/simpleperf/RecordReadThread.h b/simpleperf/RecordReadThread.h
index a12cf372..4e93f97a 100644
--- a/simpleperf/RecordReadThread.h
+++ b/simpleperf/RecordReadThread.h
@@ -124,7 +124,8 @@ class KernelRecordReader {
class RecordReadThread {
public:
RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr, size_t min_mmap_pages,
- size_t max_mmap_pages, bool allow_cutting_samples = true);
+ size_t max_mmap_pages, size_t aux_buffer_size,
+ bool allow_cutting_samples = true);
~RecordReadThread();
void SetBufferLevels(size_t record_buffer_low_level, size_t record_buffer_critical_level) {
record_buffer_low_level_ = record_buffer_low_level;
@@ -184,6 +185,7 @@ class RecordReadThread {
size_t stack_size_in_sample_record_ = 0;
size_t min_mmap_pages_;
size_t max_mmap_pages_;
+ size_t aux_buffer_size_;
// Used to pass command notification from the main thread to the read thread.
android::base::unique_fd write_cmd_fd_;
diff --git a/simpleperf/RecordReadThread_test.cpp b/simpleperf/RecordReadThread_test.cpp
index 6dcec3bd..eae58345 100644
--- a/simpleperf/RecordReadThread_test.cpp
+++ b/simpleperf/RecordReadThread_test.cpp
@@ -243,7 +243,7 @@ TEST_F(RecordReadThreadTest, handle_cmds) {
perf_event_attr attr = CreateFakeEventAttr();
records_ = CreateFakeRecords(attr, 2, 0, 0);
std::vector<EventFd*> event_fds = CreateFakeEventFds(attr, 2);
- RecordReadThread thread(128 * 1024, event_fds[0]->attr(), 1, 1);
+ RecordReadThread thread(128 * 1024, event_fds[0]->attr(), 1, 1, 0);
IOEventLoop loop;
bool has_notify = false;
auto callback = [&]() {
@@ -262,7 +262,7 @@ TEST_F(RecordReadThreadTest, handle_cmds) {
TEST_F(RecordReadThreadTest, read_records) {
perf_event_attr attr = CreateFakeEventAttr();
- RecordReadThread thread(128 * 1024, attr, 1, 1);
+ RecordReadThread thread(128 * 1024, attr, 1, 1, 0);
IOEventLoop loop;
size_t record_index;
auto callback = [&]() {
@@ -297,7 +297,7 @@ TEST_F(RecordReadThreadTest, process_sample_record) {
attr.sample_type |= PERF_SAMPLE_STACK_USER;
attr.sample_stack_user = 64 * 1024;
size_t record_buffer_size = 128 * 1024;
- RecordReadThread thread(record_buffer_size, attr, 1, 1);
+ RecordReadThread thread(record_buffer_size, attr, 1, 1, 0);
IOEventLoop loop;
ASSERT_TRUE(thread.RegisterDataCallback(loop, []() { return true; }));
@@ -348,7 +348,7 @@ TEST_F(RecordReadThreadTest, process_sample_record) {
// records even if reading one record at a time.
TEST_F(RecordReadThreadTest, has_data_notification_until_buffer_empty) {
perf_event_attr attr = CreateFakeEventAttr();
- RecordReadThread thread(128 * 1024, attr, 1, 1);
+ RecordReadThread thread(128 * 1024, attr, 1, 1, 0);
IOEventLoop loop;
size_t record_index = 0;
auto read_one_record = [&]() {
@@ -376,7 +376,7 @@ TEST_F(RecordReadThreadTest, no_cut_samples) {
perf_event_attr attr = CreateFakeEventAttr();
attr.sample_type |= PERF_SAMPLE_STACK_USER;
attr.sample_stack_user = 64 * 1024;
- RecordReadThread thread(128 * 1024, attr, 1, 1, false);
+ RecordReadThread thread(128 * 1024, attr, 1, 1, 0, false);
IOEventLoop loop;
ASSERT_TRUE(thread.RegisterDataCallback(loop, []() { return true; }));
const size_t total_samples = 100;
@@ -438,10 +438,12 @@ TEST_F(RecordReadThreadTest, read_aux_data) {
return size == aux_data[test_index].buf1.size() + aux_data[test_index].buf2.size();
};
+ const size_t AUX_BUFFER_SIZE = 4096;
+
perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
MockEventFd fd(attr, 0, nullptr, 1, true);
EXPECT_CALL(fd, CreateMappedBuffer(_, _)).Times(1).WillOnce(Return(true));
- EXPECT_CALL(fd, CreateAuxBuffer(_, _)).Times(1).WillOnce(Return(true));
+ EXPECT_CALL(fd, CreateAuxBuffer(Eq(AUX_BUFFER_SIZE), _)).Times(1).WillOnce(Return(true));
EXPECT_CALL(fd, StartPolling(_, _)).Times(1).WillOnce(Return(true));
EXPECT_CALL(fd, GetAvailableMmapDataSize(_)).Times(aux_data.size()).WillRepeatedly(Return(0));
EXPECT_CALL(fd,
@@ -452,7 +454,7 @@ TEST_F(RecordReadThreadTest, read_aux_data) {
EXPECT_CALL(fd, DestroyMappedBuffer()).Times(1);
EXPECT_CALL(fd, DestroyAuxBuffer()).Times(1);
- RecordReadThread thread(1024, attr, 1, 1);
+ RecordReadThread thread(1024, attr, 1, 1, AUX_BUFFER_SIZE);
IOEventLoop loop;
ASSERT_TRUE(thread.RegisterDataCallback(loop, []() { return true; }));
ASSERT_TRUE(thread.AddEventFds({&fd}));
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index 082b6939..7641c40e 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -93,6 +93,8 @@ constexpr size_t DEFAULT_CALL_CHAIN_JOINER_CACHE_SIZE = 8 * 1024 * 1024;
static constexpr size_t kRecordBufferSize = 64 * 1024 * 1024;
static constexpr size_t kSystemWideRecordBufferSize = 256 * 1024 * 1024;
+static constexpr size_t kDefaultAuxBufferSize = 4 * 1024 * 1024;
+
struct TimeStat {
uint64_t prepare_recording_time = 0;
uint64_t start_recording_time = 0;
@@ -180,6 +182,10 @@ class RecordCommand : public Command {
"-m mmap_pages Set the size of the buffer used to receiving sample data from\n"
" the kernel. It should be a power of 2. If not set, the max\n"
" possible value <= 1024 will be used.\n"
+"--aux-buffer-size <buffer_size> Set aux buffer size, only used in cs-etm event type.\n"
+" Need to be power of 2 and page size aligned.\n"
+" Used memory size is (buffer_size * (cpu_count + 1).\n"
+" Default is 4M.\n"
"--no-inherit Don't record created child threads/processes.\n"
"--cpu-percent <percent> Set the max percent of cpu time used for recording.\n"
" percent is in range [1-100], default is 25.\n"
@@ -321,6 +327,7 @@ class RecordCommand : public Command {
EventSelectionSet event_selection_set_;
std::pair<size_t, size_t> mmap_page_range_;
+ size_t aux_buffer_size_ = kDefaultAuxBufferSize;
ThreadTree thread_tree_;
std::string record_filename_;
@@ -477,7 +484,8 @@ bool RecordCommand::PrepareRecording(Workload* workload) {
size_t record_buffer_size = system_wide_collection_ ? kSystemWideRecordBufferSize
: kRecordBufferSize;
if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first, mmap_page_range_.second,
- record_buffer_size, allow_cutting_samples_)) {
+ aux_buffer_size_, record_buffer_size,
+ allow_cutting_samples_)) {
return false;
}
auto callback =
@@ -686,6 +694,15 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& args,
return false;
}
app_package_name_ = args[i];
+ } else if (args[i] == "--aux-buffer-size") {
+ if (!GetUintOption(args, &i, &aux_buffer_size_, 0, std::numeric_limits<size_t>::max(),
+ true)) {
+ return false;
+ }
+ if (!IsPowerOfTwo(aux_buffer_size_) || aux_buffer_size_ % sysconf(_SC_PAGE_SIZE)) {
+ LOG(ERROR) << "invalid aux buffer size: " << args[i];
+ return false;
+ }
} else if (args[i] == "-b") {
branch_sampling_ = branch_sampling_type_map["any"];
} else if (args[i] == "-c" || args[i] == "-f") {
@@ -992,7 +1009,11 @@ bool RecordCommand::AdjustPerfEventLimit() {
set_prop = true;
}
// 3. Adjust perf_event_mlock_kb.
- uint64_t mlock_kb = sysconf(_SC_NPROCESSORS_CONF) * (mmap_page_range_.second + 1) * 4;
+ long cpus = sysconf(_SC_NPROCESSORS_CONF);
+ uint64_t mlock_kb = cpus * (mmap_page_range_.second + 1) * 4;
+ if (event_selection_set_.HasAuxTrace()) {
+ mlock_kb += cpus * aux_buffer_size_ / 1024;
+ }
uint64_t cur_mlock_kb;
if (GetPerfEventMlockKb(&cur_mlock_kb) && cur_mlock_kb < mlock_kb &&
!SetPerfEventMlockKb(mlock_kb)) {
diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp
index 3e2351de..1821913e 100644
--- a/simpleperf/cmd_record_test.cpp
+++ b/simpleperf/cmd_record_test.cpp
@@ -828,4 +828,16 @@ TEST(record_cmd, cs_etm_event) {
ASSERT_TRUE(has_auxtrace_info);
ASSERT_TRUE(has_auxtrace);
ASSERT_TRUE(has_aux);
+}
+
+TEST(record_cmd, aux_buffer_size_option) {
+ if (!ETMRecorder::GetInstance().CheckEtmSupport()) {
+ GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device";
+ return;
+ }
+ ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--aux-buffer-size", "1m"}));
+ // not page size aligned
+ ASSERT_FALSE(RunRecordCmd({"-e", "cs-etm", "--aux-buffer-size", "1024"}));
+ // not power of two
+ ASSERT_FALSE(RunRecordCmd({"-e", "cs-etm", "--aux-buffer-size", "12k"}));
} \ No newline at end of file
diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp
index 6855392e..1e7f790d 100644
--- a/simpleperf/event_selection_set.cpp
+++ b/simpleperf/event_selection_set.cpp
@@ -623,10 +623,11 @@ bool EventSelectionSet::ReadCounters(std::vector<CountersInfo>* counters) {
}
bool EventSelectionSet::MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages,
- size_t record_buffer_size, bool allow_cutting_samples) {
- record_read_thread_.reset(new simpleperf::RecordReadThread(
- record_buffer_size, groups_[0][0].event_attr, min_mmap_pages, max_mmap_pages,
- allow_cutting_samples));
+ size_t aux_buffer_size, size_t record_buffer_size,
+ bool allow_cutting_samples) {
+ record_read_thread_.reset(
+ new simpleperf::RecordReadThread(record_buffer_size, groups_[0][0].event_attr, min_mmap_pages,
+ max_mmap_pages, aux_buffer_size, allow_cutting_samples));
return true;
}
diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h
index f9f38ad2..426af2f2 100644
--- a/simpleperf/event_selection_set.h
+++ b/simpleperf/event_selection_set.h
@@ -132,8 +132,8 @@ class EventSelectionSet {
bool OpenEventFiles(const std::vector<int>& on_cpus);
bool ReadCounters(std::vector<CountersInfo>* counters);
- bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, size_t record_buffer_size,
- bool allow_cutting_samples);
+ bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, size_t aux_buffer_size,
+ size_t record_buffer_size, bool allow_cutting_samples);
bool PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback);
bool SyncKernelBuffer();
bool FinishReadMmapEventData();