Faster bugreports (2/n)
- Having a system property to disable parallel run function.
- Post 'DumpTraces' to the thread pool. 3% is
improved compared with single thread run.
Bug: 136262402
Test: atest dumpstate_test
Test: atest dumpstate_smoke_test
Test: Manual enable and disable parallel run
Test: Manual trigger report using hardware key
Test: Manual trigger using bugreport shortcut
Change-Id: I2185cc3e2f429a150605d6268324c52d137db385
diff --git a/cmds/dumpstate/DumpPool.h b/cmds/dumpstate/DumpPool.h
index 266d519..a4ea875 100644
--- a/cmds/dumpstate/DumpPool.h
+++ b/cmds/dumpstate/DumpPool.h
@@ -29,26 +29,32 @@
namespace os {
namespace dumpstate {
+class DumpPoolTest;
+
/*
* A thread pool with the fixed number of threads to execute multiple dump tasks
- * simultaneously for the dumpstate. The dump task is a callable function
- * included a file descriptor as a parameter, and the task could dump results to
- * that fd. For example:
+ * simultaneously for the dumpstate. The dump task is a callable function. It
+ * could include a file descriptor as a parameter to redirect dump results, if
+ * it needs to output results to the bugreport. This can avoid messing up
+ * bugreport's results when multiple dump tasks are running at the same time.
+ * Takes an example below for the usage of the DumpPool:
*
- * void DumpXXXX(int out_fd) {
+ * void DumpFoo(int out_fd) {
* dprintf(out_fd, "Dump result to out_fd ...");
* }
* ...
* DumpPool pool(tmp_root);
- * pool.enqueueTask("TaskName", &DumpXXXX, std::placeholders::_1);
+ * pool.enqueueTaskWithFd("TaskName", &DumpFoo, std::placeholders::_1);
* ...
* pool.waitForTask("TaskName");
*
- * DumpXXXX is a callable function included a out_fd parameter. Using the
- * enqueueTask method in DumpPool to enqueue the task to the pool. The
- * std::placeholders::_1 is placeholder for DumpPool to pass a fd argument.
+ * DumpFoo is a callable function included a out_fd parameter. Using the
+ * enqueueTaskWithFd method in DumpPool to enqueue the task to the pool. The
+ * std::placeholders::_1 is a placeholder for DumpPool to pass a fd argument.
*/
class DumpPool {
+ friend class android::os::dumpstate::DumpPoolTest;
+
public:
/*
* Creates a thread pool.
@@ -72,17 +78,40 @@
void shutdown();
/*
- * Adds a task with a task name into the queue of the thread pool.
+ * Adds a task into the queue of the thread pool.
*
- * |task_name| The name of the task.
- * |f| Callable function to execute the task. This function must
- * include a parameter of file descriptor to output dump result.
+ * |task_name| The name of the task. It's also the title of the
+ * DurationReporter log.
+ * |f| Callable function to execute the task.
* |args| A list of arguments.
+ *
+ * TODO(b/164369078): remove this api to have just one enqueueTask for consistency.
*/
- template<class F, class... Args> void enqueueTask(const std::string& task_name,
- F&& f, Args&&... args) {
- auto func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
- futures_map_[task_name] = post(func);
+ template<class F, class... Args> void enqueueTask(const std::string& task_name, F&& f,
+ Args&&... args) {
+ std::function<void(void)> func = std::bind(std::forward<F>(f),
+ std::forward<Args>(args)...);
+ futures_map_[task_name] = post(task_name, func);
+ if (threads_.empty()) {
+ start();
+ }
+ }
+
+ /*
+ * Adds a task into the queue of the thread pool. The task takes a file
+ * descriptor as a parameter to redirect dump results to a temporary file.
+ *
+ * |task_name| The name of the task. It's also the title of the
+ * DurationReporter log.
+ * |f| Callable function to execute the task.
+ * |args| A list of arguments. A placeholder std::placeholders::_1 as a fd
+ * argument needs to be included here.
+ */
+ template<class F, class... Args> void enqueueTaskWithFd(const std::string& task_name, F&& f,
+ Args&&... args) {
+ std::function<void(int)> func = std::bind(std::forward<F>(f),
+ std::forward<Args>(args)...);
+ futures_map_[task_name] = post(task_name, func);
if (threads_.empty()) {
start();
}
@@ -111,13 +140,15 @@
using Task = std::packaged_task<std::string()>;
using Future = std::shared_future<std::string>;
- template<class T> Future post(T dump_func) {
+ template<class T> void invokeTask(T dump_func, const std::string& duration_title, int out_fd);
+
+ template<class T> Future post(const std::string& task_name, T dump_func) {
Task packaged_task([=]() {
std::unique_ptr<TmpFile> tmp_file_ptr = createTempFile();
if (!tmp_file_ptr) {
return std::string("");
}
- std::invoke(dump_func, tmp_file_ptr->fd.get());
+ invokeTask(dump_func, task_name, tmp_file_ptr->fd.get());
fsync(tmp_file_ptr->fd.get());
return std::string(tmp_file_ptr->path);
});
@@ -138,12 +169,21 @@
void setThreadName(const pthread_t thread, int id);
void loop();
+ /*
+ * For test purpose only. Enables or disables logging duration of the task.
+ *
+ * |log_duration| if true, DurationReporter is initiated to log duration of
+ * the task.
+ */
+ void setLogDuration(bool log_duration);
+
private:
static const int MAX_THREAD_COUNT = 4;
/* A path to a temporary folder for threads to create temporary files. */
std::string tmp_root_;
bool shutdown_;
+ bool log_duration_; // For test purpose only, the default value is true.
std::mutex lock_; // A lock for the tasks_.
std::condition_variable condition_variable_;