Generate mini-debug-info on separate thread.
The generation and compression of mini-debug-info is a lot of work.
However, we can do it on background thread when the main thread is
busy with .rodata and .text related I/O.
Change-Id: I514f1db3cb50aa250639f3ef697faa9bc9976d12
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index 05ac219..759a6d6 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -33,6 +33,8 @@
#include "leb128.h"
#include "linker/buffered_output_stream.h"
#include "linker/file_output_stream.h"
+#include "thread-inl.h"
+#include "thread_pool.h"
#include "utils.h"
namespace art {
@@ -46,6 +48,37 @@
// Let's use .debug_frame because it is easier to strip or compress.
constexpr dwarf::CFIFormat kCFIFormat = dwarf::DW_DEBUG_FRAME_FORMAT;
+class DebugInfoTask : public Task {
+ public:
+ DebugInfoTask(InstructionSet isa,
+ size_t rodata_section_size,
+ size_t text_section_size,
+ const ArrayRef<const dwarf::MethodDebugInfo>& method_infos)
+ : isa_(isa),
+ rodata_section_size_(rodata_section_size),
+ text_section_size_(text_section_size),
+ method_infos_(method_infos) {
+ }
+
+ void Run(Thread*) {
+ result_ = dwarf::MakeMiniDebugInfo(isa_,
+ rodata_section_size_,
+ text_section_size_,
+ method_infos_);
+ }
+
+ std::vector<uint8_t>* GetResult() {
+ return &result_;
+ }
+
+ private:
+ InstructionSet isa_;
+ size_t rodata_section_size_;
+ size_t text_section_size_;
+ const ArrayRef<const dwarf::MethodDebugInfo>& method_infos_;
+ std::vector<uint8_t> result_;
+};
+
template <typename ElfTypes>
class ElfWriterQuick FINAL : public ElfWriter {
public:
@@ -55,6 +88,9 @@
~ElfWriterQuick();
void Start() OVERRIDE;
+ void PrepareDebugInfo(size_t rodata_section_size,
+ size_t text_section_size,
+ const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) OVERRIDE;
OutputStream* StartRoData() OVERRIDE;
void EndRoData(OutputStream* rodata) OVERRIDE;
OutputStream* StartText() OVERRIDE;
@@ -75,6 +111,8 @@
File* const elf_file_;
std::unique_ptr<BufferedOutputStream> output_stream_;
std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
+ std::unique_ptr<DebugInfoTask> debug_info_task_;
+ std::unique_ptr<ThreadPool> debug_info_thread_pool_;
DISALLOW_IMPLICIT_CONSTRUCTORS(ElfWriterQuick);
};
@@ -147,6 +185,26 @@
}
template <typename ElfTypes>
+void ElfWriterQuick<ElfTypes>::PrepareDebugInfo(
+ size_t rodata_section_size,
+ size_t text_section_size,
+ const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
+ if (compiler_options_->GetGenerateMiniDebugInfo()) {
+ // Prepare the mini-debug-info in background while we do other I/O.
+ Thread* self = Thread::Current();
+ debug_info_task_ = std::unique_ptr<DebugInfoTask>(
+ new DebugInfoTask(builder_->GetIsa(),
+ rodata_section_size,
+ text_section_size,
+ method_infos));
+ debug_info_thread_pool_ = std::unique_ptr<ThreadPool>(
+ new ThreadPool("Mini-debug-info writer", 1));
+ debug_info_thread_pool_->AddTask(self, debug_info_task_.get());
+ debug_info_thread_pool_->StartWorkers(self);
+ }
+}
+
+template <typename ElfTypes>
void ElfWriterQuick<ElfTypes>::WriteDebugInfo(
const ArrayRef<const dwarf::MethodDebugInfo>& method_infos) {
if (compiler_options_->GetGenerateDebugInfo()) {
@@ -154,13 +212,11 @@
dwarf::WriteDebugInfo(builder_.get(), method_infos, kCFIFormat, true /* write_oat_patches */);
}
if (compiler_options_->GetGenerateMiniDebugInfo()) {
- // Generate only some information and compress it.
- std::vector<uint8_t> xz_elf_file = MakeMiniDebugInfo(
- builder_->GetIsa(),
- builder_->GetRoData()->GetSize(),
- builder_->GetText()->GetSize(),
- method_infos);
- builder_->WriteSection(".gnu_debugdata", &xz_elf_file);
+ // Wait for the mini-debug-info generation to finish and write it to disk.
+ Thread* self = Thread::Current();
+ DCHECK(debug_info_thread_pool_ != nullptr);
+ debug_info_thread_pool_->Wait(self, true, false);
+ builder_->WriteSection(".gnu_debugdata", debug_info_task_->GetResult());
}
}